Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Throwing Destructors, Memory Corruption?

We have a class whose semantic behaviour is like the following :-

struct Sample
{
  ~Sample() throw() 
  {
    throw 0;
  }
};

void f ()
{
  try
  {
    delete new Sample;
  }
  catch (...){
  }
}

I know that throwing exceptions in dtors is evil; but the relinquishment of a 3rd Party library resource is throwing an exception (but can be re-accquired immediately, something strange!). There is also a pool of this resource, say an array/container of class Sample. So, there are two cases to consider: destruction of a dynamically allocated object and destruction of a dynamically allocated array of objects.

Currently the application crashes randomly at different execution-points only when the array version (pool) is used. We believe this is due to memory corruption but then why does the unpooled version work?.

What happens to the allocated memory? Is it undefined behaviour? What happens in the case of an array? Do the dtors (atleast, not memory) of all the elements of an array (say if the dtor of the first element throws) get called?

Thanks in advance,

EDIT-1: Well, we tracked it down to dtors of some array-elements not being called. But the allocated memory does not seem to have problems... Following is section 5.3.5.7 of SC22-N-4411.pdf)

If the value of the operand of the delete-expression is not a null pointer value, the delete-expression will
call a deallocation function (3.7.4.2). Otherwise, it is unspecified whether the deallocation function will be
called. [ Note: The deallocation function is called regardless of whether the destructor for the object or some
element of the array throws an exception. —end note ]

<\snip>

Looks like memory is always deallocated in such cases. Am i right in interpreting the standard?

like image 644
Abhay Avatar asked Jan 30 '26 01:01

Abhay


2 Answers

There are two things that could happen in this situation:

  • terminate() is called
  • undefined behaviour

In neither case can dynamically allocated memory be guaranteed to be released (except that application termination will of course return all resources to the OS).

C++ will terminate your application if a dtor throws an exception while the stack is being unwound because of another exception.

As it's practically impossible to determine under what circumstances a dtor is called, the standard rule is to never throw exceptions from dtors.

If your 3rd Party Library is throwing an exception, catch it in your dtor, log it, or save it's state to some static cache where you can pick it up "later", but don't allow it to escape out of your dtor.

Do this, then see if your collection of objects work, it could be causing your crashes.

UPDATE

Unfortunately I'm not a spec lawyer, preferring the Fisherman's Friend approach of "suck it an see".

I'd write a small app with a class that allocates a meg off the heap. In a loop, make an array of the classes, have the classes dtor throw an exception, and throw a catch an exception at the end of the loop (causing the stack to unwind and call the dtors of the array of classes) and watch it to see your VM usage go through the roof (which I'm pretty sure it will).

Sorry I can't give you chapter and verse, but that's my "belief"

like image 32
Binary Worrier Avatar answered Jan 31 '26 19:01

Binary Worrier