Sign in to follow this  
Chozo

g++ exceptions

Recommended Posts

Not sure if this would be better in the Unix forum or not, but maybe others here have had this experience. We've got 3 binaries that we compile here. The first 2 compile and run just fine. They catch exceptions and so on just dandily. All 3 binaries share a common source base that is where the exceptions are thrown at. The third binary, when compiled, will always call terminate() when an exception is thrown (we explicitely do NOT use exception specifications to avoid the hassle they bring, and the stack trace shows no sign of an unexpected exception). We've even tried something like this: try { throw std::exception(); } catch(...) { } and terminate() is *still* called. We're pretty much at our wits end here. We can't figure out why the first 2 binaries work just fine and the third fails. As I said, they share a common source base and they use the same compile options. Is it a bug in gcc 3.3.x or am I maybe doing something wrong somewhere? We've also thrown on -fexceptions and -fno-enforce-eh-specs but to no avail. I appreciate any help ideas anyone might have.

Share this post


Link to post
Share on other sites
Quote:
Original post by Chozo
try {
throw std::exception();
} catch(...) {
}

and terminate() is *still* called. We're pretty much at our wits end here. We can't figure out why the first 2 binaries work just fine and the third fails. As I said, they share a common source base and they use the same compile options. Is it a bug in gcc 3.3.x or am I maybe doing something wrong somewhere?
It's always the compiler's fault isn't it? [wink]

If it's nothing but that above code, then I'd say compiler bug, but it's not nothing but the above code, is it?

Share this post


Link to post
Share on other sites
Of course not. :)
It's about 100,000 lines of code all mashed together to make a mess no one dares walk through. I suppose that's the only thing to do isn't it? Walk through it all one line at a time... ugh.

Share this post


Link to post
Share on other sites
Quote:
Original post by Chozo
Of course not. :)
It's about 100,000 lines of code all mashed together to make a mess no one dares walk through. I suppose that's the only thing to do isn't it? Walk through it all one line at a time... ugh.


Better idea:

gdb ./mess_no_one_dares_walk_through
...
(gdb) break main
...
(gdb) run
...
(gdb) catch throw
...
(gdb) run
...
(gdb) bt
...


It's possible that finding out the exact thrown exception will help you figure out what's going on... (edit: and that will at least get you to the part where the exception is being thrown) - just my 2 cents. Is it possible you have something like this in an inner branch of logic:

try
{
}
catch(...)
{
terminate();
}


?

Share this post


Link to post
Share on other sites
Are you using throw() specifiers somewhere? When an exception is thrown in a function with a throw specifier iirc. unexpected() is called, which by default calls terminate().

Share this post


Link to post
Share on other sites
We turned off exception specifications, just to make sure that wasn't it.

I'll try that gdb run through tomorrow and see what comes up. We've used a bt from the terminate() and we think that leads us back to the exception. Never know though (and it never hurts to try).

Thanks for the suggestions. If you've got any more, I'd love to hear them. This has been a heck of a confusing ordeal.

Share this post


Link to post
Share on other sites
There shouldn't be any. I can't guarantee it, but I'm pretty sure there aren't any. If there are... someone's in some trouble. ;)

Share this post


Link to post
Share on other sites
Here's the output of the gdb session:

Quote:

(gdb) break main
Breakpoint 1 at 0x805f819
(gdb) run --console
Starting program: /soft/DEV/shane/bin/opodsrvr --console
[Thread debugging using libthread_db enabled]
[New Thread 16384 (LWP 17972)]
[Switching to Thread 16384 (LWP 17972)]

Breakpoint 1, 0x0805f819 in main ()
(gdb) catch throw
Catchpoint 2 (throw)
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) n
Program not restarted.
(gdb) cont
Continuing.

Catchpoint 2 (exception thrown)
__cxa_throw (obj=0x821052c, tinfo=0x82111e0, dest=0x82111e0 <typeinfo for ConfigurationException>) at /usr/local/src/gcc/gcc-3.2.2/libstdc++-v3/libsupc++/eh_throw.cc:59
59 /usr/local/src/gcc/gcc-3.2.2/libstdc++-v3/libsupc++/eh_throw.cc: No such file or directory.
in /usr/local/src/gcc/gcc-3.2.2/libstdc++-v3/libsupc++/eh_throw.cc
Current language: auto; currently c++
(gdb) bt
#0 __cxa_throw (obj=0x821052c, tinfo=0x82111e0, dest=0x82111e0 <typeinfo for ConfigurationException>) at /usr/local/src/gcc/gcc-3.2.2/libstdc++-v3/libsupc++/eh_throw.cc:59
#1 0x08191e34 in ApplicationSection::instanceSubNode(std::string) const ()
#2 0x08182e4e in AppServerConfiguration::AppServerConfiguration(EnvironmentConfiguration const&, std::string) ()
#3 0x08053654 in AppConfiguration::AppConfiguration(std::string) ()
#4 0x08053c92 in AppConfiguration::init(std::string const&, std::string const&) ()
#5 0x0805f8b5 in main ()
(gdb) cont
Continuing.

Program received signal SIGABRT, Aborted.
0xb6cbf251 in kill () from /lib/libc.so.6
(gdb) bt
#0 0xb6cbf251 in kill () from /lib/libc.so.6
#1 0xb6c4ccff in pthread_kill () from /lib/libpthread.so.0
#2 0xb6c4d07a in raise () from /lib/libpthread.so.0
#3 0xb6cbeff4 in raise () from /lib/libc.so.6
#4 0xb6cc0393 in abort () from /lib/libc.so.6
#5 0xb7a260c9 in __cxxabiv1::__terminate(void (*)()) (handler=0xb6cc02b8 <abort>) at /usr/local/src/gcc/gcc-3.2.2/libstdc++-v3/libsupc++/eh_terminate.cc:47
#6 0xb7a26103 in std::terminate() () at /usr/local/src/gcc/gcc-3.2.2/libstdc++-v3/libsupc++/eh_terminate.cc:57
#7 0xb7a26230 in __cxa_throw (obj=0x82704a0, tinfo=0x0, dest=0) at /usr/local/src/gcc/gcc-3.2.2/libstdc++-v3/libsupc++/eh_throw.cc:77
#8 0x08191e34 in ApplicationSection::instanceSubNode(std::string) const ()
#9 0x08182e4e in AppServerConfiguration::AppServerConfiguration(EnvironmentConfiguration const&, std::string) ()
#10 0x08053654 in AppConfiguration::AppConfiguration(std::string) ()
#11 0x08053c92 in AppConfiguration::init(std::string const&, std::string const&) ()
#12 0x0805f8b5 in main ()
(gdb)


As you can see, it's not very helpful. The very first exception being thrown is the one that causes terminate() to be called. I'm not sure what the eh_throw.cc error is all about, but it's shown up on every version of g++ I've tried (and I've tried a lot of them). I did a quick grep on terminate just to be sure, but nothing came up. Is there anything else I could try?

Share this post


Link to post
Share on other sites
eh_throw.cc is a source file in the C++ Library. If you were to type 'up 7' to go back up to that frame, followed by 'list', it should show you the code where it decided to call terminate, which would probably give you an idea of why it was called in the first place.

Share this post


Link to post
Share on other sites
list just produces output like this:

59 in /usr/local/src/gcc/gcc-3.2.2/libstdc++-v3/libsupc++/eh_throw.cc

or

42 in /usr/local/src/gcc/gcc-3.2.2/libstdc++-v3/libsupc++/eh_terminate.cc

Nothing more. Is that something meaningful?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
To me it seems like the problem is in iApplicationSection::instanceSubNode(std::string) , not in the files eh_throw.cc eh_terminate.cc at all.

Share this post


Link to post
Share on other sites
All that is, is the try/catch block. I can replace all that's in the try {} section with throw std::exception() and have the catch block try to catch it and it'll still crash. That's what leads me to believe it's something about exceptions not being setup properly.

Share this post


Link to post
Share on other sites
Quote:
Original post by Chozo
All that is, is the try/catch block. I can replace all that's in the try {} section with throw std::exception() and have the catch block try to catch it and it'll still crash. That's what leads me to believe it's something about exceptions not being setup properly.
Are you sure that an exception wasn't thrown before that?

Did you put that try catch block as the first thing in your main() function and still have this happen?

Share this post


Link to post
Share on other sites
Yup. The whole of main is a try { ... } catch(some exception) { } catch(some other exception) { } catch(yet another exception) { } catch(...) { }. So whatever doesn't get caught early on should get caught there, right?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Well on windows (...) will catch everything, including system exception such as access violations and such. On linux, I think it will only catch C++ exceptions (which is all that the standard requires). Still, it's very strange because throwing a std::exception IS a C++ exception...

Share this post


Link to post
Share on other sites
Those files (eh_throw.cc and eh_terminate.cc and so on) don't exist on my machine. Anywhere. I have no idea wth they're doing in there.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by Chozo
Those files (eh_throw.cc and eh_terminate.cc and so on) don't exist on my machine. Anywhere. I have no idea wth they're doing in there.


They are not something you really need to care about. They are source files that are part of the C++ standard library. I would guess there is enough debugging info left in the library to tell you the name of the source files. When it goes here, it has already thrown, though. The problem, which may be a memory access violation, is in ApplicationSection::instanceSubNode(std::string) const

Share this post


Link to post
Share on other sites
They're all being caught by reference. I've heard that someone else got it to compile on Debian and Fedora. I find it really hard to believe that the distribution has anything to do with this, but who knows.

Share this post


Link to post
Share on other sites
Well seeing as this appears to be still unresolved let's try and narrow down the possible area of problems:

1) does a basic exception example work?

#include <iostream>
using namespace std;

int main ( void )
{
try { throw 3; }
catch (...) { cout << "OK" << endl; }
}


no) FUBARed compiler/linker setup.

2) does the same example work catch std::exception and throwing std::logic_error (in <stdexcept>)?

no) FUBARed library (and/or compiler/linker) setup.
yes) it's probably something with your code.

Possibilities so far at this point:

1) destructor throws during stack unwinding from the first throw. (gdb) break catch then step through with detailed line debugging info avail would be a good idea - you might get away with a simple (gdb) continue after hitting the first exception - in theory it'll then break again on the second throw (I'm not sure exactly how stack unwinding plays about with the stack...).

2) someone was naughty and messed with the exception handlers somewhere without telling anyone.

3) If indeed someone got it compiling and working on a linux box, guesses are either FUBARed environment or you've got a wild pointer/dangling reference somewhere screwing everything up.

Share this post


Link to post
Share on other sites
Okay, I made a simple test:


#include <stdexcept>
#include <iostream>

int main(int argc, char* argv[])
{
std::string errorstr("crap");

try {
throw std::runtime_error(errorstr);
} catch(...) {
std::cout << "Caught something?" << std::endl;
}

return 0;
}




And compiled with g++ -Wall. It worked just dandily. I have this code at the *start* of our module:


int main(int argc, char *argv[])
{
std::set_terminate(terminate_func);
std::set_unexpected(unexpected_func);

std::cout << "Before exception!" << std::endl;
try {
throw 3;
} catch(...) {
std::cerr << "Damn!" << std::endl;
exit(1);
}
std::cout << "After exception!" << std::endl;




And it calls the terminate handler after printing 'Before exception!'. 'Damn!' and 'After exception!' are never printed. Does that mean some global object might be mangling the stack? If so... how would I find it?

Share this post


Link to post
Share on other sites
Extremely odd. Does this code work (standalone)? What are your sources for terminate/unexpected_func?

#include <exception>
#include <iostream>

using namespace std;

void terminate_func( void )
{
cout << "terminate_func()" << endl;
abort();
}

void unexpected_func( void )
{
cout << "unexpected_func()" << endl;
terminate();
}

int main ( int argc , char * argv [] )
{
std::set_terminate( terminate_func );
std::set_unexpected( unexpected_func );

std::cout << "Before exception!" << std::endl;
try
{
throw 3;
}
catch ( ... )
{
std::cerr << "Damn!" << std::endl;
exit(1);
}
std::cout << "After exception!" << std::endl;
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this