[Gc] workaround for C++ exceptions problem

Filip Pizlo pizlo at mac.com
Wed Jan 25 19:57:50 PST 2006


On Jan 25, 2006, at 10:01 PM, skaller wrote:

> On Wed, 2006-01-25 at 16:20 -0500, Filip Pizlo wrote:
> []
>
> The point of what I'm saying is that whoever tries to modify
> the GC/C++runtime to work with C++ exceptions in g++, must find out
> what happens to 'the' exception when another one is legally raised,
> and, in what way 'the' exception is restored when the current
> one is no longer required.

Sure.  Overriding __cxa_allocate_exception() gives us this for free.   
Agreed?

>
>
> This can happen in two completely distinct circumstances:
>
> (a) the exception is caught, but in the catch block,
> another exception is thrown.
>
> (b) the exception is NOT caught, but in some
> destructor another exception is thrown.
>
> in BOTH cases, there is a new 'top' exception which
> must be stored in the 'top' exception slot, and in
> both cases the old exception in that slot must be
> saved on some kind of stack so it can be restored
> when and if the new exception is handled.

Yeah, the code I'm looking at (see eh_catch.cc) seems to have a nifty  
linked list for this.

>
> In other words, there must be a stack of currently
> in flight exceptions, by BOTH our definitions.
>
> You know where the top of that stack is.
> Where is the rest of it??

I know where the whole stack is.  Each element of the stack is  
malloced separately using a separate call to __cxa_allocate_exception().

If you look at my proposed GC_THROW() routine, then you also know.   
Here it is again:

template< typename T >
void GC_THROW(const T &exn) {
    try {
       throw exn;
    } catch (const T &exn) {
       void *ptr=&exn;
       // ptr is the location of the exception slot
       throw;
    }
}

>
> Are the exceptions pushed onto the machine stack?
> Or are they chained together in a linked list?

Linked list, at least in the code I'm looking at.

>
> Both implementations are viable. In both cases
> the GC MIGHT be able to keep track of everything
> just knowing the top slot, assuming it is in a fixed
> place (which is stupid since it isn't thread safe unless
> that place is in TLS)

I tried to determine from the C++ spec if there are some constraints  
here.  Couldn't figure it out.

My guess is that the linked list approach is so much more efficient  
that nobody is going to do it any other way.

>
> Filip proposes to actually force the
> exception allocation and deallocation to go thru
> calls to the gc, and mark the objects as fresh roots
> on allocation, and unroot them on deallocation
> so they become collectable.
>
> Hans proposal is simpler: to mark the region containing
> the pointer to the object as a root, and allocate
> the exception objects as non-roots.

Hmmm.  I didn't understand Hans' proposal that way.  I thought the  
point was to make a copy of the exception so that you know what  
pointers it has.  Or is this saying the same thing?

Perhaps it is because I don't see Hans' proposal this way, but I  
think that with my hacks, Hans' proposal is less brittle than mine.   
It doesn't require knowing what the ABI is, only that once an  
exception is dropped into its slot, it stays there.  Of course, there  
is actually no guarantee that this will be the case, but both  
proposals are equally flawed in this regard.

> The Linux C++ ABI changed recently, it created months of work
> for Linux distro maintainers such as Ubuntu and Debian.

This is a non-stop issue for anyone using C++ in GCC.  But I've been  
following the basic exception throwing machinery for quite some time,  
and it always seems to have had the same basic elements.  So I feel  
quite comfortable overriding __cxa_allocate_exception/ 
__cxa_free_exception.

-Filip



>
> -------
> The current gcc implementation of catch sucks, it doesn't
> work properly across DLL boundaries -- so the ABI may
> well change again  :)
>
>
> -- 
> John Skaller <skaller at users dot sf dot net>
> Felix, successor to C++: http://felix.sf.net
>



More information about the Gc mailing list