|
|
Subscribe / Log in / New account

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.


to post comments

GCC begins move to C++

Posted Jun 1, 2010 16:11 UTC (Tue) by rev (guest, #15082) [Link] (11 responses)

Sorry, but you are wrong. The very same applies when you don't use exceptions. You have to constantly ask yourself questions like 'does this function return an error code?'. You have to deal with or delegate such error codes at virtualy every line of code you write.

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.

GCC begins move to C++

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 auto_ptr<> and RAII besides exceptions in his example above.

consider for instance:

void f(void)
{
    T * p = malloc (sizeof (T));
    g(p);
    free(p);
}

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.

GCC begins move to C++

Posted Jun 1, 2010 17:03 UTC (Tue) by avik (guest, #704) [Link] (2 responses)

It's possible to transition incrementally:

1. Pick a function
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

If correctly applied, an entire code base can be converted with very little explicit try/catch blocks remaining.

GCC begins move to C++

Posted Jun 1, 2010 17:23 UTC (Tue) by dgm (subscriber, #49227) [Link] (1 responses)

It's certainly doable, but I would bet the cost is too high to make it worthy. I believe the GCC code base is above one million LOC. Assuming half include a function call, the task looks daunting.

GCC begins move to C++

Posted Jun 1, 2010 18:01 UTC (Tue) by avik (guest, #704) [Link]

I have successfully applied this technique to a code base that was about a quarter of that size (though considerably less gnarly). Whether it will be worth the effort or not is very subjective.

GCC begins move to C++

Posted Jun 2, 2010 11:13 UTC (Wed) by gowen (guest, #23914) [Link]

How about...

void f(void)
{
    T p;
    g(&p);
}

GCC begins move to C++

Posted Jun 2, 2010 18:01 UTC (Wed) by Cyberax (✭ supporter ✭, #52523) [Link] (3 responses)

This code will most probably SEGFAULT in C if allocation fails and malloc() returns NULL.

Is it better than a thrown exception?

You are right of course...

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.

malloc() failure

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.

malloc() failure

Posted Jun 7, 2010 9:47 UTC (Mon) by nye (subscriber, #51576) [Link]

There are other reasons malloc can fail beyond having no free memory. In zfs-fuse they recently had to add code to increase max_map_count dynamically because ZFS makes so many allocations that it could easily blow right past the default limit, causing memory allocation failures.

GCC begins move to C++

Posted Jun 3, 2010 5:44 UTC (Thu) by njs (subscriber, #40338) [Link] (1 responses)

That code is incorrect in C -- it fails to check g's return value for an error code. This may be (often is) a *much* more serious error than a leak.

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!

GCC begins move to C++

Posted Jun 3, 2010 16:41 UTC (Thu) by dgm (subscriber, #49227) [Link]

Why? Maybe I don't care if there is a problem with g, or I could do nothing sensible.

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.
@Cyberax: maybe g() can handle the NULL case gracefully, as it should if properly written.

GCC begins move to C++

Posted Jun 2, 2010 1:31 UTC (Wed) by dvdeug (guest, #10998) [Link] (4 responses)

If you convert the C statement "a = b + c();" directly into C++, the only place where exceptions can come up is if c() suddenly throws exceptions. If the causes don't matter then make c() not throw exceptions--if you don't control the source, you can always add an inline wrapper around it. If it does matter, then for a straightforward conversion you don't need to change anything and both the C and C++ programs will do poorly defined, unpleasant things in the presence of errors.

GCC begins move to C++

Posted Jun 2, 2010 13:53 UTC (Wed) by dgm (subscriber, #49227) [Link] (3 responses)

> If you convert the C statement "a = b + c();" directly into C++, the only place where exceptions can come up is if c() suddenly throws exceptions.

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.
2. + can be an overloaded operator, and thus can also throw.
3. = can need to create a temporary object, whose constructor can also throw.

AFAIK, the only thing that cannot throw is "b".

GCC begins move to C++

Posted Jun 2, 2010 14:37 UTC (Wed) by mjthayer (guest, #39183) [Link]

> 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.
> 2. + can be an overloaded operator, and thus can also throw.
> 3. = can need to create a temporary object, whose constructor can also throw.

I think the OP was talking about code directly converted from C, so those things should not apply.

GCC begins move to C++

Posted Jun 3, 2010 0:24 UTC (Thu) by dvdeug (guest, #10998) [Link] (1 responses)

If either = or + in a = b + c(); can throw exceptions, then it's not the same code. You're looking at something like

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.

GCC begins move to C++

Posted Jun 3, 2010 16:31 UTC (Thu) by dgm (subscriber, #49227) [Link]

Exactly, remember that it could not be the case initially, but the project will hopefully continue evolving, and thus the assumptions that made the code correct will change.

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!).


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