0

When an exception is thrown, then the block where it is thrown is unwinded from stack:

int main ()
{
    try
    {
        Object x; // doesn't throw
        Object y; // throws
        cout << "wonderful";
    }
    catch (...)
    {
        cout << "fail";
    }
}

When Object allocates on construction memory on heap and deallocates it properly on destruction, then there should be no memory leak, because stack unwinding calls destructor of x (not of y, but Object guarantees, that when constructor failing, then no memory leak). As far all right, isn't it?

Let's go into depth:

int main ()
{
    Object x; // doesn't throw
    double *d = new double[256*256*256]; // doesn't throw
    Object y; // throws
    cout << "wonderful";
    delete[] d;
}

Because of good education, I want to clean my trash up by myself, and not let do it the OS. I know, that every modern OS deletes by itself heap memory of a program which terminates unexpected (or expected, but no explicit deallocation). So in the upper case, the deallocation of d would do my OS, but x would be still properly deallocating its memory (because of stack unwinding and destructor call) before OS would do it, right?

What about that:

#include <cstdlib>

int main ()
{
    Object x; // doesn't throw
    try { Object y; } // throws
    catch (...) {  cout << "fail"; exit(EXIT_FAILURE); }
    cout << "working and working...";
    cin.get();
}

Is the destructor of x called before exit gives control back to OS?

And more in depth:

void Object::be_stupid ()
{
    Object a; // doesn't throw
    try { Object b; }// throws
    catch (...) { exit(EXIT_FAILURE); }
}

void main ()
{
    Object x; // doesn't throw
    try { x.be_stupid(); } // exits program
}

Is the constructor of x called before exit gives control back to OS? If yes, then exit "unwinds" all surrounding stacks including main(), right?

trincot
  • 317,000
  • 35
  • 244
  • 286
mb84
  • 683
  • 1
  • 4
  • 13
  • 1
    exit does NOT unwind like an exception throw does. But as your program is just about to die as you call it, it really doesn't need to. Same goes for other "die now" functions such as std::terminate. –  Dec 13 '13 at 22:19
  • @polkadotcadaver: While resources are cleaned up by the OS, it could still be desirable to get objects destroyed, e.g., to get buffered streams flushed. However, `exit()` indeed doesn't do any local clean-up (it still cleans up global objects). – Dietmar Kühl Dec 13 '13 at 22:26
  • 1
    @DietmarKühl I agree - always better to handle cleanup gracefully, especially where RAII is used more imaginatively than new/delete. –  Dec 13 '13 at 22:29
  • You can check out [this answer](http://stackoverflow.com/a/3486544/531122). It explains in detail how throws can cause a memory leak. – Steve Van Opstal Dec 13 '13 at 22:33
  • @polkadotcadaver: (and all:) so also when I don't use any `exit()` and have no `try/catch` block inside `main()`, then these `Objects` on the stack in `main()` are not deallocated by themselves, but by OS? So there is no other possibility than having a `try` block surrounding the whole `main()` code? Or having a globas static garbage collector class instance that calls destructors explicitely (after their adresses had been passed from `main()` to it)? – mb84 Dec 13 '13 at 22:45
  • 1
    @mb84 Declare main as int main() and instead of exit just return, then everything will be cleaned up as it would be when leaving any function, and the program will exit and clean up static objects too. –  Dec 13 '13 at 22:47
  • @polkadotcadaver: of course! I already forgot this possibility... thanks! – mb84 Dec 13 '13 at 22:51

1 Answers1

0

Ok, got it thanks to polkadotcadaver: never use exit(), propagate exceptions until main() and do there a simple return - all stack Objects will be deallocated by their own destructor before OS takes control.

mb84
  • 683
  • 1
  • 4
  • 13