Sign in to follow this  
Wavarian

Catching STL Exceptions

Recommended Posts

Just a quick question, should I catch a bad_alloc exception that an std::list might throw when adding an item to it? Also, is this the only exception that can be thrown by a list? Cheers

Share this post


Link to post
Share on other sites
Lets get one thing straight standard library containers & algorithms *typically* don't throw exceptions but your user-defined types might and can, the default allocator type std::allocator uses the throw version of global operator new. In the case of your user-defined type's constructor throwing exceptions *typically* its caught, resources are released and the exception is rethrown to inform you.

Quote:
Original post by Wavarian
is this the only exception that can be thrown by a list?


if your user-defined types don't throw any exceptions then yes its the only possible one for std::list

Share this post


Link to post
Share on other sites
Thanks for the help - ratings have been given.

It's just that I have two lists, and if an item is successfully inserted into the first list, but not into the other (due to such an exception), then it makes sense for me to remove the item from the first list before rethrowing the exception.

All is well =)

Share this post


Link to post
Share on other sites
Just a warning, trying to keep two containers (lists in your case) "in sync" is usually a maintenance nightmare and a "smell" that something is wrong with the code design - however, suggesting an appropriate fix would require more knowledge of exactly what you're trying to do.

As for std::bad_alloc(), I would suggest that chances are you're completely screwed anyway (or damn near) if that ever gets thrown, because you're out of memory - might be better at that point to just save what data you can and let your program get the hell out of Dodge.

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
Just a warning, trying to keep two containers (lists in your case) "in sync" is usually a maintenance nightmare and a "smell" that something is wrong with the code design - however, suggesting an appropriate fix would require more knowledge of exactly what you're trying to do.


Just as a general example, it's probably better to do something like this:

std::list< std::pair< int, Object* > > g_ObjectIndices;
g_ObjectIndices.insert(std::make_pair(1, &MyObj));
std::pair< int, Object* >& TempPair = *g_ObjectIndices.front();
if(TempPair.first == SomeIndex) Use(TempPair.second);


This is by no means the only way to do it, but should give you some idea of how you can keep "two lists" "synced" using just one list.

Share this post


Link to post
Share on other sites
Yeah I figured the same in the end.

But don't worry about my design - in my posts, I try to give very simple and clear examples in order to get the answer I'm looking for. So don't look any deeper than you need to =D

EDIT: Well I might has well mention what I'm doing. I have two classes, kind of like a service / consumer or an event source / listener. Each class has a list, ie a service has a list of subscribed consumers, and a consumer has a list of active services.

When a consumer "dies", it needs to tell the service not to try calling it anymore, and thus removes itself from the service's list. The same happens vice-versa.

I figured that if I was attaching a consumer object to a service object, then if the service managed to add itself to the consumer's list, but the consumer was unable to be added to the service's list, then once the service dies, the consumer would be trying to access the invalid service pointer when it is being destroyed.

Share this post


Link to post
Share on other sites
Trying to handle std::bad_alloc exceptions is a bad idea (to do anything other than report an error that is).

To effectivley recover from a bad_alloc the very least you have to do is somehow remember what it is you were trying to construct, then free some memory, then try to construct again. Then repeat until you successfully allocate.

A much better way is to use a new handler function as new handlers take care of most of the above automatically.

Share this post


Link to post
Share on other sites
Handling std::bad_alloc doesn't necesssarily mean trying to make it succeed. A catch block for std::bad_alloc may do other things like back out of database transactions or transmit error signals over a network connection. Basically whenever you have a set of operations that should be collectively atomic, but multiple operations may throw an exception, then handling exceptions like std::bad_alloc is appropriate,

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
Handling std::bad_alloc doesn't necesssarily mean trying to make it succeed. A catch block for std::bad_alloc may do other things like back out of database transactions or transmit error signals over a network connection. Basically whenever you have a set of operations that should be collectively atomic, but multiple operations may throw an exception, then handling exceptions like std::bad_alloc is appropriate,


Point taken.

I should have been a bit more specific in my post.



Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
Handling std::bad_alloc doesn't necesssarily mean trying to make it succeed.


Yeah, trying to "make it succeed" is the domain of the new_handler. See the std::set_new_handler() function. That function is called when new fails to allocate memory. Only if it cannot make more memory available (e.g. garbage collection) does std::bad_alloc get thrown (by the new_handler).

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