GCC begins move to C++
GCC begins move to C++
Posted Jun 1, 2010 15:53 UTC (Tue) by dgm (subscriber, #49227)In reply to: GCC begins move to C++ by zorro
Parent article: GCC begins move to C++
The basic problem with exceptions is that they can pop up anywhere, changing control flow. Doing this in an existing code base, and doing it right, is really _hard_, not unlikely trying to make existing code thread safe.
Think for instance:
a = b + c();
this is a pretty innocent statement in C. Enter C++, where it can involve several constructors, destructors, method calls and overloaded operator invocations, all potentially throwing different kinds of exceptions, so you really should be doing:
try { a = b + c(); } catch (exception * e) { // STL exception manage_standard_exception(e); } catch (LibException * e) { // unstandard exceptions thrown by a third party library manage_lib_exception(e); } catch (...) { // catch everything else... manage_unknown_exception(); }
Exception safe code doesn't happen by chance. You have to plan for it, be careful and program defensively, always asking yourself "what if an exception is thrown just here?". It doesn't matter that It cannot happen today, because code evolves and can very well happen tomorrow.
If you try to add exceptions as an afterthought the probability that you will miss several critical places is high.
Posted Jun 1, 2010 16:11 UTC (Tue)
by rev (guest, #15082)
[Link] (11 responses)
It's just that exceptions automate and hide what you would otherwise write explicitly: return error codes to a point in the call tree where the error is handled. They are a language construct that expresses exactly what you would otherwise have to tediously code.
In more recent langauges exception than C++ have the benefit of having to handle an exception: failing to do so is a compile error. Whereas with classic error handling it is easy to forget to deal with an error situation.
Posted Jun 1, 2010 16:36 UTC (Tue)
by dgm (subscriber, #49227)
[Link] (10 responses)
return codes don't change control flow. That's the reason avik had to introduce consider for instance:
This code does not leak memory in C, but can leak in C++ with exceptions.
Remember we are talking about a _large_ amount of C code that was not written with exceptions in mind.
Posted Jun 1, 2010 17:03 UTC (Tue)
by avik (guest, #704)
[Link] (2 responses)
1. Pick a function
If correctly applied, an entire code base can be converted with very little explicit try/catch blocks remaining.
Posted Jun 1, 2010 17:23 UTC (Tue)
by dgm (subscriber, #49227)
[Link] (1 responses)
Posted Jun 1, 2010 18:01 UTC (Tue)
by avik (guest, #704)
[Link]
Posted Jun 2, 2010 11:13 UTC (Wed)
by gowen (guest, #23914)
[Link]
Posted Jun 2, 2010 18:01 UTC (Wed)
by Cyberax (✭ supporter ✭, #52523)
[Link] (3 responses)
Is it better than a thrown exception?
Posted Jun 3, 2010 21:07 UTC (Thu)
by khim (subscriber, #9252)
[Link]
This is exactly why you CAN'T write such code in gcc. malloc is forbidden there at include file level. Instead you'll use xmalloc - it can not ever return NULL, so there are no need to check the error code.
Posted Jun 4, 2010 9:46 UTC (Fri)
by jrn (subscriber, #64214)
[Link] (1 responses)
On Linux, this is true but mostly irrelevant. Most systems overcommit (it is hard to find a saner thing to do if the user wants large programs to be able to fork() but does not provide the swap to back them) and malloc almost never fails.
Posted Jun 7, 2010 9:47 UTC (Mon)
by nye (subscriber, #51576)
[Link]
Posted Jun 3, 2010 5:44 UTC (Thu)
by njs (subscriber, #40338)
[Link] (1 responses)
You're assuming that g-written-in-C cannot fail, while g-written-in-C++ can, and then saying that that makes C better... which I guess is true given your assumptions, but if you have a method to write error-free code in C then you should share *that*, it'd be a much more compelling argument!
Posted Jun 3, 2010 16:41 UTC (Thu)
by dgm (subscriber, #49227)
[Link]
What I assume is that g-written-in-C cannot change the flow of control. That assumption doesn't hold in C++ with exceptions. That doesn't make C better, just different. Different enough, in fact, that converting C code straight to C++ is not that easy.
By the way:
@gowen: it's just an example.
Posted Jun 2, 2010 1:31 UTC (Wed)
by dvdeug (guest, #10998)
[Link] (4 responses)
Posted Jun 2, 2010 13:53 UTC (Wed)
by dgm (subscriber, #49227)
[Link] (3 responses)
You would be surprised. I recommend you to read this http://www.gotw.ca/gotw/020.htm
In this concrete example:
1. c() can indeed throw an exception in the code, but can also propagate uncaught exceptions from any code called within, possibly including constructors.
AFAIK, the only thing that cannot throw is "b".
Posted Jun 2, 2010 14:37 UTC (Wed)
by mjthayer (guest, #39183)
[Link]
I think the OP was talking about code directly converted from C, so those things should not apply.
Posted Jun 3, 2010 0:24 UTC (Thu)
by dvdeug (guest, #10998)
[Link] (1 responses)
a = copy_foo (add_foo (b, c()));
in C. If C++ would have thrown an exception, then a will have an error code in it (and a will have to support error values, and that value will have to be checked just like you have to catch an exception), a will have trash in it (and you'll have to check it--if you can) or the whole thing will crash, like if copy_foo assumes that add_foo can't return errors or trash.
Posted Jun 3, 2010 16:31 UTC (Thu)
by dgm (subscriber, #49227)
[Link]
That's basically the problem. Adding exceptions to an established code base changes basic assumptions programmers would probably have made (nobody in his right mind would lose time writing exception-safe code if your language has no exceptions!).
GCC begins move to C++
GCC begins move to C++
auto_ptr<>
and RAII besides exceptions in his example above.
void f(void)
{
T * p = malloc (sizeof (T));
g(p);
free(p);
}
GCC begins move to C++
2. Modify its callers to expect exceptions from it (adding try/catch if necessary)
3. Convert it to throw exceptions instead of returning error codes
4. Modify it to expect exceptions from its callees (removing try/catch if necessary)
5. Repeat
GCC begins move to C++
GCC begins move to C++
How about...GCC begins move to C++
void f(void)
{
T p;
g(&p);
}
GCC begins move to C++
You are right of course...
malloc() failure
malloc() failure
GCC begins move to C++
GCC begins move to C++
@Cyberax: maybe g() can handle the NULL case gracefully, as it should if properly written.
GCC begins move to C++
GCC begins move to C++
2. + can be an overloaded operator, and thus can also throw.
3. = can need to create a temporary object, whose constructor can also throw.
GCC begins move to C++
> 1. c() can indeed throw an exception in the code, but can also propagate uncaught exceptions from any code called within, possibly including constructors.
> 2. + can be an overloaded operator, and thus can also throw.
> 3. = can need to create a temporary object, whose constructor can also throw.
GCC begins move to C++
GCC begins move to C++