LWN.net Logo

C vs. C++ vs. ...

C vs. C++ vs. ...

Posted Jul 1, 2012 15:43 UTC (Sun) by nix (subscriber, #2304)
In reply to: C vs. C++ vs. ... by daniel
Parent article: Why learn C? (O'Reilly Radar)

If you write the same program in C and C++ and compile it with GCC you will get the same object code because they use the same code generator and optimizer.
That's wrong: some transformations are done at the language-dependent tree stage, and these can differ between C and C++. Further, the languages have distinct constraints on the optimizer. e.g.:
Even exceptions these days are compiled so that exception handling generates code only on the throw path
That's wrong: C++ code that doesn't use exceptions can still have them thrown through it at any points not marked nothrow (or marked as extern "C" or something similar to indicate the impossibility of exceptions emanating from those points), so not only are cleanup regions required, but a large number of additional abnormal edges are introduced which can and do constrain the optimizer. Thus, you'd often get different code compiling C code as C versus compiling it as C++, even if the optimizers and code generators were completely identical.


(Log in to post comments)

C vs. C++ vs. ...

Posted Jul 4, 2012 12:52 UTC (Wed) by jwakely (subscriber, #60262) [Link]

marked as extern "C" or something similar to indicate the impossibility of exceptions emanating from those points
extern "C" doesn't mean any such thing.
#include <stdio.h>
struct E { };
extern "C" void f();
int main()
{
    try {
        f();
    } catch (const E&) {
        puts("Caught");
    }
}
extern "C" void f() { throw E(); }

C vs. C++ vs. ...

Posted Jul 4, 2012 13:37 UTC (Wed) by andresfreund (subscriber, #69562) [Link]

As far as I can see this is undefined behaviour because youre throwing an exception through C linkage which the stack unwinding/exception propagation process doesn't have to be able to do.

C vs. C++ vs. ...

Posted Jul 4, 2012 15:10 UTC (Wed) by nix (subscriber, #2304) [Link]

It's not undefined behaviour so much as it might just not work. Some functions in glibc (e.g. qsort()) are explicitly compiled with -fexceptions so as to support C++ exceptions thrown through qsort() from the callback function, but this is very rare: I've never seen it in C code outside glibc, even for C functions that invoke callbacks.

C vs. C++ vs. ...

Posted Jul 4, 2012 15:17 UTC (Wed) by andresfreund (subscriber, #69562) [Link]

Why is that a contradiction to being undefined behaviour?

C vs. C++ vs. ...

Posted Jul 4, 2012 18:30 UTC (Wed) by jwakely (subscriber, #60262) [Link]

1) I never claimed it had to work, my point is that extern "C" does not mean "cannot throw".

2) It doesn't _have_ to work, but it can work (which would make it closer to implementation-defined or conditionally-supported, not undefined) and does with (at least) GCC, Clang and Solaris CC. There's even a cross-platform standard describing it. For a nice overview of the "personalities" that are used to support mixed-language exceptions to propagate through call frames using different languages see http://llvm.org/docs/ExceptionHandling.html

C vs. C++ vs. ...

Posted Jul 4, 2012 15:08 UTC (Wed) by nix (subscriber, #2304) [Link]

Oooh. Interesting. Given that 99% of C libraries are not compiled with -fexceptions and do not specify anything nothrow-related in their prototypes (of course not, they're C), this suggests that G++ is introducing a very large number of unnecessary abnormal edges for exceptions potentially raised in calls to such functions that cannot possibly ever be thrown. I wonder how much this is impairing optimization?

C vs. C++ vs. ...

Posted Jul 4, 2012 15:51 UTC (Wed) by scottt (subscriber, #5028) [Link]

> Given that 99% of C libraries are not compiled with -fexceptions

Note that Red Hat and Fedora has been building the whole distro with -fexceptions for years:

rpmbuild --showrc | grep cflags
-14: __global_cflags	-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions <...>
I suspect other distros do the same.

C vs. C++ vs. ...

Posted Jul 4, 2012 18:43 UTC (Wed) by jwakely (subscriber, #60262) [Link]

Doesn't the stack have to be unwound similarly for thread cancellation?

The C frames don't need to do any cleanup (no destructors) and should just let the exception propagate unhindered, until it reaches a frame with the right C++ personality to handle it.

I might be completely wrong, but I don't see any obvious reasons the generated code should be different.

Copyright © 2013, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds