Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stop execution without skipping destructors

Is it possible to terminate software execution without skipping calls to destructors? For instance, in the code below, the destructor for test will never be called because of the exit(1) statement.

#include <iostream>
#include <cstdlib>
using namespace std;

class A{
public:
    A(){cout << "Constructed.\n";}
    ~A(){cout << "Destroyed.\n";}
};

void func()
{
    //Assuming something went wrong:
    exit(1);  
}

int main(int argc, char *argv[])
{
    A test;
    func();
    return 0;
}

What I need, is a way to end the program (from within func()) that calls all necessary destructors before terminating. So far I've been handling this through func() return value, as in:

bool func()
{
    //Assuming something went wrong:
    return false;
}

int main(int argc, char *argv[])
{
    A test;
    if( !func() )return 1;
    return 0;
}

The problem with this method is that it quickly becomes very annoying (and code bloating) to manage once you need to apply it to a series of nested functions.

Is there a way of achieving the same results of the second example (proper destructor calls) with a syntax similar to the first example (call exit(1) wherever you are)?

like image 921
Malabarba Avatar asked Nov 29 '11 15:11

Malabarba


People also ask

Does Exit 0 call destructors?

When exit(0) is used to exit from program, destructors for locally scoped non-static objects are not called. But destructors are called if return 0 is used.

Why did the destructor not execute?

Because you have a memory leak.

Are destructors necessary?

We know that if a destructor is not provided, the compiler will generate one. This means that anything beyond simple cleanup, such as primitive types, will require a destructor. In many cases, dynamic allocation or resource acquisition during construction, has a clean up phase.

Does Ctrl C call destructor?

If you run this program and press control-C, you should see the word "destructor" printed.


3 Answers

Throw an exception, catch it in main and return.

This relies on nothing else catching your exception without rethrowing it.

like image 147
JoeG Avatar answered Sep 30 '22 19:09

JoeG


You could rely on stack unwinding for this: when you want to exit, throw an exception and catch it in main().

like image 27
NPE Avatar answered Sep 30 '22 21:09

NPE


struct my_exit
{
    int error;
    int operator()()
    {
        // do any cleanup on globals
        return error;
    }
};

int main()
{
    try
    {
        doSomethingThatCouldCauseExit();
    }
    catch (my_exit & me)
    {
        // Clean up globals now
        exit(me());
    }
}
like image 29
Michael Price Avatar answered Sep 30 '22 21:09

Michael Price