the behavior of g++ 3.3.1 exception

C

chenchang

Hi, experts. i write a simple program to test EH in G++:

void throwfunction()
{
throw "test";
}

class A
{
int i;
public:
A(int I):i(I){
cout<<"---------------------------A:"<< i <<"-----------------------\n";
}
~A()
{
cout<<"--------------------------~A:"<< i <<"-----------------------\n";
}
};

int main(int ,char*)
{
A b(1);
throwfunction();
cout << "---after throw--------------\n";
return 0;
}

According to TC++ 3rd(14.4.2),"resource acquisition is initialization". I
think the result should be :
-------------A:1---------------------
------------~A:1---------------------

but the result is :
-------------A:1---------------------
//..there are some message for prompting to dump statck frame.

what is the reason?

In addition, i add try..catch.. in the main:

int main(int ,char*)
{
try
{
A b(1);
throwfunction();
cout << "---after throw--------------\n";
}
catch(...)
{
throw;
}
return 0;
}

the result is:
-------------A:1---------------------
------------~A:1---------------------
//..there are some message for prompting to dump statck frame.

it is the expected result, but why?
 
K

Kevin Goodsell

chenchang said:
Hi, experts. i write a simple program to test EH in G++:

void throwfunction()
{
throw "test";
}

class A
{
int i;
public:
A(int I):i(I){
cout<<"---------------------------A:"<< i <<"-----------------------\n";

If you are using 'cout', you must have some code you didn't bother to
show us (otherwise your compiler would almost certainly have rejected
the code). Please review FAQ 5.8.
}
~A()
{
cout<<"--------------------------~A:"<< i <<"-----------------------\n";
}
};

int main(int ,char*)

This is not a legal definition of main(). The two arguments to main(),
if used, must be of type 'int' and 'char**' (or equivalent) respectively.

If you aren't using the arguments, just leave them out.
{
A b(1);
throwfunction();

This throws an exception that you don't bother to catch. The result is a
call to terminate(), which by default calls abort(). Whether or not
stack unwinding occurs first is implementation-defined.
cout << "---after throw--------------\n";
return 0;
}

According to TC++ 3rd(14.4.2),"resource acquisition is initialization". I
think the result should be :
-------------A:1---------------------
------------~A:1---------------------

That's a possible result.
but the result is :
-------------A:1---------------------
//..there are some message for prompting to dump statck frame.

I'm not sure if that's a strictly conforming result or not, but it seems
reasonable.
what is the reason?

In addition, i add try..catch.. in the main:

int main(int ,char*)

Same problem as other main().
{
try
{
A b(1);
throwfunction();
cout << "---after throw--------------\n";
}
catch(...)
{
throw;

This throws an exception that you don't bother to catch.
}
return 0;
}

the result is:
-------------A:1---------------------
------------~A:1---------------------
//..there are some message for prompting to dump statck frame.

it is the expected result, but why?

Why not?

Maybe you should read a little bit more about exception handling. Only
the things constructed during the 'try' block's execution are destructed
as the result of an exception, and that's only required if the exception
is caught. Anything automatic object constructed before the try block
will be destructed as usual, at the end of the scope (or by an exception
caught in an enclosing dynamic scope).

-Kevin
 
C

chenchang

hi kevin:
Maybe you should read a little bit more about exception handling. Only
the things constructed during the 'try' block's execution are destructed
as the result of an exception, and that's only required if the exception
is caught. Anything automatic object constructed before the try block
will be destructed as usual, at the end of the scope (or by an exception
caught in an enclosing dynamic scope).

Please refer to 14.4 The C++ Programming Language (Third Edition):
"The Destructor will be called independently of whether the function is
exited normally or exited an exception is thrown."

it tells me that we need not declare an automatic object in try block!

Sorry, I forgot to say that i am running G++ under the windows.
 
H

Hans-Christian Stadler

I think the behaviour you see is reasonable, because you don't flush
the cout stream.

Maybe
cout << ".. ~A:i .." << flush;
will give the result that you expected.

Hans
 
T

tom_usenet

hi kevin:


Please refer to 14.4 The C++ Programming Language (Third Edition):
"The Destructor will be called independently of whether the function is
exited normally or exited an exception is thrown."

it tells me that we need not declare an automatic object in try block!

Yes, but this only applies if the exception is caught eventually. If
the exception propogates out of main, then "terminate" is called, and
stack unwinding might not occur. The moral: never let any exceptions
escape from main - to do so is a bug.

Tom
 
R

Rolf Magnus

chenchang said:
Please refer to 14.4 The C++ Programming Language (Third Edition):
"The Destructor will be called independently of whether the function
is exited normally or exited an exception is thrown."

it tells me that we need not declare an automatic object in try block!

Still, you don't catch the exception, so abort() is called. And abort()
doesn't destroy local objects.
 
D

Dave Moore

chenchang said:
hi kevin:


Please refer to 14.4 The C++ Programming Language (Third Edition):
"The Destructor will be called independently of whether the function is
exited normally or exited an exception is thrown."

Please refer to the rest of chapter 14 in TC++PL, specifically 14.7
.... there you will find exactly what Kevin already told you, that an
uncaught exception generates implementation-defined behavior,
particularly with regard to whether or not destructors are called.
The phrase you quoted from 14.4 is only referring to objects that were
in scope when the exception was thrown ... look at the preceeding
example in the book.
 
K

Kevin Goodsell

Hans-Christian Stadler said:
I think the behaviour you see is reasonable, because you don't flush
the cout stream.

Maybe
cout << ".. ~A:i .." << flush;
will give the result that you expected.

Please quote the relevant context from the message you are replying to
so that people reading your message know to what you are referring.

Streams are flushed when they are destroyed, so explicit flushing isn't
necessarily needed. However, exiting the program via abort() (via
terminate(), via an uncaught exception) may not destroy existing
objects. In fact, it may be required NOT to (I'd have to check to be
sure). So this could feasibly be part of the problem, but a more general
solution would be to not let exceptions go uncaught.

-Kevin
 
D

Dave Moore

Please refer to the rest of chapter 14 in TC++PL, specifically 14.7
... there you will find exactly what Kevin already told you, that an
uncaught exception generates implementation-defined behavior,
particularly with regard to whether or not destructors are called.

This is correct and relevant to OP's example ...
The phrase you quoted from 14.4 is only referring to objects that were
in scope when the exception was thrown ... look at the preceeding
example in the book.

This is correct, but not relevant to OP's example .. no scoping issues
exist in his code AFAICS .. its just the uncaught exception causing
havoc .. sorry for any confusion
 

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,013
Latest member
KatriceSwa

Latest Threads

Top