Question

I have "inherited" a design where we are using a few global objects for doing stuff when the application exits (updating application status log files, etc ... not important to the question).

Basically the application creates dummy helper objects of specific classes and lets their destructor do these extra works when the application exits either normally or when an error was encountered (and the application knows what to do in all the cases, again not relevant to the question).

But now I have encountered a situation where I do not want to call these destructors, just leave the application without executing these "termination jobs". How can I do this in a decent, platform independent way? I do not want a solution such as divide with zero :)

Edit: I know the design is broken :) We are working on fixing it.

Edit2: I would like to avoid any "trace" of abnormal exit... Sorry for late specification.

Edit3: Obtaining access to the source code for the destructors in order to modify them is very difficult. This happens when politicians take over the keyboard and try to write programs. We just know, that "their" destructor will run on exit...

Was it helpful?

Solution

How can I do this in a decent, platform independent way?

You can't. At least not in a decent way.

You can accomplish this by throwing an exception and not catching it. The end result will be that your application will terminate quite ungracefully. Destructors will not be called. This is quite ugly, very hackish. If your design relies on this behavior to function correctly, well not only is your design completely demented, but it will be near-impossible to maintain.

I would prefer setting a boolean flag in the objects you don't want to run the destructors for. If this flag is set, then the destruction code would not be run. The destructors will still fire, but the actual code you want to avoid running can be skipped.


If you control the construction of the global, you might be able to leverage operator placement-new. Construct a global char buffer big enough for your global, then placement-new your global there. Since objects constructed this way must be destroyed by explicitly calling the destructor, simply don't call the destructor on shutdown for the global.

OTHER TIPS

abort();

Aborts the current process, producing an abnormal program termination.

The function raises the SIGABRT signal (as if raise(SIGABRT) was called). This, if uncaught, causes the program to terminate returning a platform-dependent unsuccessful termination error code to the host environment.

The program is terminated without destroying any object and without calling any of the functions passed to atexit or at_quick_exit.

Taking your comment of "we know it's broken"...

Put a global bool somewhere

bool isExiting;

Set this to true when exiting.

In your destructors do

if( !global::isExiting )
{
   // destruction code here
}

Hide somewhere, and be thoroughly ashamed.

The easiest is to replace the global objects by heap-allocated pointers to the objects. That way, in order to run their destructors, you have to manually delete them. Be aware that this is of course very, very nasty. A better way than using a raw pointer is to use a std::unique_ptr and, in case the destructor shouldn’t be called, release it.

If you don’t want to change the client code which is interacting with the global objects (and expect a non-pointer type), just wrap the actual pointer into a global proxy object.

(PS: There are few but very legitimate reasons for such a design. Sometimes it’s entirely safe not to call destructors, and calling them may be detrimental, e.g. because it’s known that they only release memory, but will take very long due to many nested destructor calls. This still needs to be done very carefully but is not at all “bad design”.)

It is ugly but it works:

  1. Create simple maker class.

  2. Maker's constructorr should allocate the object of your liking and assign it to a static pointer.

  3. Make sure that nothing is done in maker's destructor.

  4. Create single static instance of maker object.

  5. To make things look better, make the static pointer private andwrite inline accessor function that will convert the static pointer you have to a public reference.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top