C++ exceptions and destructors

M

Magalie

Hi!

I've got a question concerning C++ exceptions, more precisely the
stack unwinding when an exception occurs. We agree that when an
exception is thrown, all objects that have destructors are
"destructed" by calling the corresponding destructor. This is most
often what is wanted. However,I have a special situation where this is
NOT what I'd like to happen : indeed, i'd like to keep my objects
living on the stack. Practically, this would be to implement a
function tracing method that would be able, when my program crashes
(exception !), to tell me in which function it happened, just like
unreal.
Is there a way of telling the compiler that an object should not be
destroyed upon exception ? Or, is there a way to know that the
destructor gets called because of an exception and not because the
function exited "normally" ?

Thanks in advance !
Magalie
 
?

=?iso-8859-1?Q?Juli=E1n?= Albo

Magalie escribió:
Is there a way of telling the compiler that an object should not be
destroyed upon exception ? Or, is there a way to know that the
destructor gets called because of an exception and not because the
function exited "normally" ?

You can allocate the object with new and delete it just before the
function exits... and take care when you add a new "return" to the
function.

Alternatively, you can have an object of a handle class that in his
destructor checks std::uncaught_exception () and destroys or not the
object handled in each case.

In any case you probably need also a way to store pointers to the
allocated and not deleted objects.

Regards.
 
R

Ron Natalie

Magalie said:
. However,I have a special situation where this is
NOT what I'd like to happen : indeed, i'd like to keep my objects
living on the stack.

There is no way to do this. The stack containing these objects
ceases to exist once the catch block is reached.
Practically, this would be to implement a
function tracing method that would be able, when my program crashes
(exception !), to tell me in which function it happened, just like
unreal.

So why don't you put special code in the destructors to record this information?
Is there a way of telling the compiler that an object should not be
destroyed upon exception ?
No.

Or, is there a way to know that the
destructor gets called because of an exception and not because the
function exited "normally" ?

One scheme that I have used to implement a similar feature is to use
a special exception object that I throw, that when it is constructed sets
a static bool that says I'm handling exceptions, then the TraceBack objects
check that in their destructor and if so log their destruction.

A few macros that initalizie the TraceBack object with __FILE__ and __LINE__
give more information on the trace.
 
I

Ivan Vecerina

Hi,
[....all ok....]
Practically, this would be to implement a
function tracing method that would be able, when my program crashes
(exception !), to tell me in which function it happened, just like
unreal.
Is there a way of telling the compiler that an object should not be
destroyed upon exception ?
No, except by allocating it on the heap and manually destroying it
upon function exit.
Or, is there a way to know that the
destructor gets called because of an exception and not because the
function exited "normally" ?
Well, there is a function called uncaught_exception() which
returns a boolean. Unfortunately, it cannot be used reliably:
http://www.gotw.ca/gotw/047.htm

So regarding what you are trying to implement, here's what I
would suggest:
If you are ok with using platform-specific features,
some compilers do provide a way to access information
about enclosing stack frames in debug mode. Please ask
in a forum dedicated to your platform.
Alternatively, information about the enclosing calls
should be made available to the exception-throwing code.

Here's a quick overview of what I would try:

class ScopeInfo {
private:
static ScopeInfo* head; // or use TLS for threaded app
//NB: don't forget define&init in a cpp file...
ScopeInfo* const next;
char const* const info;
ScopeInfo(ScopeInfo const&); // not-implemented
public:
ScopeInfo(char const* info_)
: next(head), info(info_) { head=this; };
~ScopeInfo() { head=next; }

static print() {
std::cerr << " In scope:\n";
for( ScopeInfo* p = head ; p ; p=p->next )
std::cerr << p->info << '\n';
}
};

- ScopeInfo are instantiated on the stack as desired
- on throw location, call ScopeInfo::print (or store
the info within the exception)

That's just an option I can think of -- I'm curions
if there are any other ideas...


Cheers,
Ivan
 
A

Alexander Terekhov

Magalie said:
Hi!

I've got a question concerning C++ exceptions, more precisely the
stack unwinding when an exception occurs. We agree that when an
exception is thrown, all objects that have destructors are
"destructed" by calling the corresponding destructor.

"We" don't agree. This only makes sense if there's a handler (in
the dynamic context) to catch AND HANDLE your exception -- you'd
really want to fully unwind the stack then (and only then).
This is most
often what is wanted. However,I have a special situation where this is
NOT what I'd like to happen : indeed, i'd like to keep my objects
living on the stack.

Uncaught exception shall invoke unexpected() without any stack
unwinding. The only problem is that unexpected() is {currently}
invoked only on ES violation, AFTER silly unwinding, and with
totally messed up terminate() and unexpected() handlers.

http://groups.google.com/[email protected]
(Subject: Re: A few exception questions)
Practically, this would be to implement a
function tracing method that would be able, when my program crashes
(exception !), to tell me in which function it happened, just like
unreal.

Do you know what "core dumped" mean? Or are you on a Sutter's
"platform"? ``Hear hear.''

http://search.microsoft.com/search/results.aspx?qu=Userdump

regards,
alexander.
 
J

jeffc

Magalie said:
Hi!

I've got a question concerning C++ exceptions, more precisely the
stack unwinding when an exception occurs. We agree that when an
exception is thrown, all objects that have destructors are
"destructed" by calling the corresponding destructor. This is most
often what is wanted. However,I have a special situation where this is
NOT what I'd like to happen : indeed, i'd like to keep my objects
living on the stack. Practically, this would be to implement a
function tracing method that would be able, when my program crashes
(exception !), to tell me in which function it happened, just like
unreal.
Is there a way of telling the compiler that an object should not be
destroyed upon exception ? Or, is there a way to know that the
destructor gets called because of an exception and not because the
function exited "normally" ?

I think the normal way to do that would be to add that information to a
parameter passed on the exception itself. For example

void functionA()
{
throw "Error in functionA";
}

Of course, you can get more sophisticated and throw exceptions of your own
classes, with more information inside them.
 
B

Big Brian

We agree that when an
exception is thrown, all objects that have destructors are
"destructed" by calling the corresponding destructor.

No, this is not what happens. Destructors are called only when
objects go out of scope, or delete is called on object created with
new. Consider the following..

#include <iostream>

class foo
{
std::string s_;
public:
foo(std::string s):s_(s) {}
~foo() { std::cout << s_ << "'s ~foo()"<< std::endl;}
};

int main(int argc , char * argv[])
{
try
{
foo * f ( new foo("f") );
foo x("x");
throw 1;
}
catch(int e)
{
std::cout << "in catch, e=" << e << std::endl;
}
}


When executed, it prints...

x's ~foo()
in catch, e=1

The destructor for the object pointed to by f doesn't get called
because it never goes out of scope. That's why they implemented
auto_ptr. Its used like this...

#include <iostream>
#include <memory>

class foo
{
std::string s_;
public:
foo(std::string s):s_(s) {}
~foo() { std::cout << s_ << "'s ~foo()"<< std::endl;}
};

int main(int argc , char * argv[])
{
try
{
std::auto_ptr<foo> f( new foo("f") );
foo x("x");
throw 1;
}
catch(int e)
{
std::cout << "in catch, e=" << e << std::endl;
}
}


When run, it prints the following...


x's ~foo()
f's ~foo()
in catch, e=1

This is most
often what is wanted. However,I have a special situation where this is
NOT what I'd like to happen : indeed, i'd like to keep my objects
living on the stack.

This can only happen if those object don't go out of scope. Like
this...

#include <iostream>
#include <memory>

class foo
{
std::string s_;
public:
foo(std::string s):s_(s) {}
~foo() { std::cout << s_ << "'s ~foo()"<< std::endl;}
};

int main(int argc , char * argv[])
{
std::auto_ptr<foo> f( new foo("f") );
foo x("x");

try
{
throw 1;
}
catch(int e)
{
std::cout << "in catch, e=" << e << std::endl;
}
}


This prints the following

in catch, e=1
x's ~foo()
f's ~foo()

Thus, the object x and f are still on the stack when the exception is
caught.
Practically, this would be to implement a
function tracing method that would be able, when my program crashes
(exception !), to tell me in which function it happened, just like
unreal.

If you load the core file produced when your program crashes into a
debugger, you will get the same information.
Is there a way of telling the compiler that an object should not be
destroyed upon exception ?

The compiler doesn't destroy anything just because of an exception
being thrown, in fact you need to make sure that you destroy things
that need to be destroyed yourself, that's why auto_ptr is so nice.
Basically, the compiler only destroyes objects which go out of scope.
 
J

jeffc

Big Brian said:
No, this is not what happens. Destructors are called only when
objects go out of scope, or delete is called on object created with
new.

But that is exactly what happens as the stack unwinds. Surely, the original
poster did not literally mean "all objects" - he/she meant all objects
"below" the catch in scope. I doubt anyone thinks all objects at the same
scope as the exception handler are also wiped out.
 
R

Ron Natalie

jeffc said:
But that is exactly what happens as the stack unwinds. Surely, the original
poster did not literally mean "all objects" - he/she meant all objects
"below" the catch in scope. I doubt anyone thinks all objects at the same
scope as the exception handler are also wiped out.

Well actually, everything in the try block and things descended from it. It certainly
does not destroy things in the scope of the exception handler (they ahven't been
created yet).

SomeClass A;
try {
SomeClass B;
function_call();
} catch(...) {
SomeClass C;
}

WHen the catch begins, A is still valid, B and everyting in function_call and beyond
is destroyed, C has not yet been created.
 
J

jeffc

Ron Natalie said:
Well actually, everything in the try block and things descended from it. It certainly
does not destroy things in the scope of the exception handler (they ahven't been
created yet).

Right, I should have said that in terms of the try block, not the catch.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top