Jump to content
  • Advertisement
Sign in to follow this  
Desperado

Exception safety question in C++

This topic is 3641 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello folks, I have a question regarding "exception safe" functions: As far as I understand, a function can be called exception safe if it doesn't leak ressources. However, if that method allocates memory on heap via new, when must that memory be deleted so the function is still considered exception safe? During stack-unwinding (using smart pointers)? Or can it be as late as in the catch clause? And if the destructor of one of the allocated objects throws, does your function have to be able to fix this to be exception safe? Thanks for your admittance

Share this post


Link to post
Share on other sites
Advertisement
The most fundamental requirement for an exception-safe function is to leave the program in a valid state if the execution leaves the function as an exception (as opposed to normal returning). This means that, before an exception leaves the function, any allocated but unreferenced resources must be released (regardless of whether through RAII or a catch block).

A more advanced, and useful, requirement for an exception-safe function is to leave the program in the same state it was in when the function was called, if the execution leaves the function as an exception. This means that not only will all unreferenced resources be released, but any changes applied to the program state will be reversed before the execution leaves the function. Again, how you do this is irrelevant as long as it's done.

Share this post


Link to post
Share on other sites
Quote:
And if the destructor of one of the allocated objects throws


Last I remember, destructors aren't supposed to throw.

Quote:
As far as I understand, a function can be called exception safe if it doesn't leak ressources


Exception-safe function must preserve data integrity. This means more than just releasing the resources, it means going as far as being ACID compliant.

For handling dynamic allocations, auto_ptr is sometimes used. Other types of smart pointers can be used, but auto_ptr comes with language, and is adequate for this purpose.

Quote:
when must that memory be deleted so the function is still considered exception safe

A function either executes completely, or all the changes made are reverted back.

This means, if an exception occurs in during function call, it's as if it were never called before. This is a binary condition, there's no such thing as reasonable exception safety.

The Exceptional C++ covers this topic extensively.

Share this post


Link to post
Share on other sites
Quote:
Original post by Desperado
Hello folks, I have a question regarding "exception safe" functions:

As far as I understand, a function can be called exception safe if it doesn't leak ressources. However, if that method allocates memory on heap via new, when must that memory be deleted so the function is still considered exception safe? During stack-unwinding (using smart pointers)? Or can it be as late as in the catch clause?


It has to be done by the throwing function, because (a) that's the whole point (you clean up your mess and others clean up their mess); (b) the catch clause can't clean it up, because how is it going to know how?

Quote:
And if the destructor of one of the allocated objects throws


This doesn't happen. A throwing destructor means "I couldn't cause this thing to cease to exist properly". You have BIG problems if that's possible.

Share this post


Link to post
Share on other sites
There are 4 levels of exception safety:


  1. no-throw - the function never throws exceptions.

  2. strong exception guarantee - when the function exits via an exception it does
    not change program state and no resources are leaked

  3. basic exception guarantee - when the function exits via an exception it leaves
    the program in a legal state and no resources are leaked

  4. not exception safe - when the function exits via an exception no guarentees are made about the state of the program



The first 3 are collectively refered to as the Abrahams' guarantees (named after David Abrahams, of boost fame). You should always implement the highest exception guarantee you can reasonably accomplish.

So in answer to your questions:
Quote:

As far as I understand, a function can be called exception safe if it doesn't leak ressources.

That's required, but not sufficient, for exception safety.

Quote:
However, if that method allocates memory on heap via new, when must that memory be deleted so the function is still considered exception safe? During stack-unwinding (using smart pointers)?

Stack unwinding is fine, as is a catch clause within the function, but not catch clauses elsewhere.

Quote:
And if the destructor of one of the allocated objects throws, does your function have to be able to fix this to be exception safe?

Destructors should always always always implement the no-throw guarantee, but don't have to go so far as to make themselves safe if another destructor called within the first destructor throws (it's impossible to make a destructor safe for this anyway).

Share this post


Link to post
Share on other sites
@all: That answers most of my questions, thank you!

One final thing:

A function is exception safe, but not exception neutral if it preserves the program state but doesn't throw an exception to inform the caller, right?

Share this post


Link to post
Share on other sites
Quote:
Original post by Desperado
@all: That answers most of my questions, thank you!

One final thing:

A function is exception safe, but not exception neutral if it preserves the program state but doesn't throw an exception to inform the caller, right?


If it doesn't throw an exception, then it... doesn't throw an exception. That's the no-throw guarantee.

If code called from within the function throws an exception, and the function doesn't catch it, it's exactly the same - from the POV of these guarantees - as if the exception was generated locally.

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
Quote:
Original post by Desperado
@all: That answers most of my questions, thank you!

One final thing:

A function is exception safe, but not exception neutral if it preserves the program state but doesn't throw an exception to inform the caller, right?


If it doesn't throw an exception, then it... doesn't throw an exception. That's the no-throw guarantee.

If code called from within the function throws an exception, and the function doesn't catch it, it's exactly the same - from the POV of these guarantees - as if the exception was generated locally.


This brings up something interesting, because you can violate program state without emitting the exception. For example, the exception could be caught silently (or an error code ignored) but the program could be left in an awkward state due to it. Is that beyond the scope of the exception guarantees?

Share this post


Link to post
Share on other sites
Quote:
Original post by Rydinare

This brings up something interesting, because you can violate program state without emitting the exception. For example, the exception could be caught silently (or an error code ignored) but the program could be left in an awkward state due to it. Is that beyond the scope of the exception guarantees?


You break it, you buy it.

Not much else can be said here. Language cannot prevent programmer bugs.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!