-1

I was studying about the RAII mechanism in C++ which replaces the finally of Java. I wrote the following code to test it:

void foo(int* arr) {
    cout << "A" << endl;
    throw 20;
    cout << "B" << endl;
}

class Finally {
private:
    int* p;
public:
    Finally(int* arr) {
        cout << "constructor" << endl;
        p = arr;
    }

    ~Finally() {
        cout << "destructor" << endl;
        delete(p);
    }
};

int main()
{
    int * arr = new int[10];
    new Finally(arr);
    try {
        foo(arr);
    } catch (int e) {
        cout << "Oh No!" << endl;
    }
    cout << "Done" << endl;
    return 0;
}

I want to free the memory which I used for arr so I set a new class Finally which saves the pointer to the array and when it exits the scope it should call the destructor and free it. But the output is:

constructor
A
Oh No!
Done

No call for the destructor. It also does not work when I move the body of main to some other void method (like void foo()). What fix should I do to achieve the desired action?

vesii
  • 2,760
  • 4
  • 25
  • 71
  • 4
    C++ is not Java. You are writing C++ code as if it was Java. Naturally, it doesn't work as you expect. You also fundamentally misunderstand RAII. A proper RAII will `new` ***in the constructor*** and not somewhere else. It will also provide a copy constructor and an assignment operator as well, that does the right thing; or delete them. Finally, `new` in `main()` is completely totally wrong. C++ does not work this way. – Sam Varshavchik Sep 14 '19 at 13:09
  • 3
    RAII does not "replace the `finally` block in Java". Java's `finally` block is a (bad) attempt at compensating for not having deterministic destructors. – Pete Becker Sep 14 '19 at 13:33
  • 1
    In general, `new` should be considered "advanced", only only used by people with many years of experience and only rarely even then. – Mooing Duck Sep 14 '19 at 15:54

2 Answers2

2

That's because the object you create with new Finally(arr) doesn't really gets destructed in your program.

Your allocation of the object just throws the object away immediately, leading to a memory leak, but more importantly it's created outside the scope of the try and catch.

For it to work you have to do something like

try {
    Finally f(arr);
    foo(arr);
} catch (int e) {
    cout << "Oh No!" << endl;
}

That would create a new object f in the try, which will then get destructed when the exception is thrown (as well as when it goes out of scope of the try if no exception is thrown).

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1

You're assuming C++ works liked Java. It doesn't, so there are actually a few things wrong in your code

The statement

 new Finally(arr);

dynamically allocates a Finally, but it is NEVER released in your code. Hence its destructor is never called.

Instead do

 Finally some_name(arr);

This will invoke the destructor of Finally - at the end of main() - which will give the output your expect.

However, the second thing wrong is that the destructor of Finally does delete (p) which gives undefined behaviour, since p is the result (in main()) of new int [10]. To give the code well-defined behaviour, change delete (p) to delete [] p.

Third, with the two fixes above, you are not using RAII. RAII means "Resource Acquisition Is Initialisation", which is not actually what your code does. A better form would be to initialise p using a new expression in Finallys constructor and release it with a correct delete expression in the destructor.

class Finally
{
     private:
        int* p;
     public:
        Finally() : p(new int [10])
        {
            cout << "constructor" << endl;
        };

       ~Finally()
       {
           cout << "destructor" << endl;
           delete [] p;
       };

       int *data() {return p;};
};

AND replace the first two lines of your main() with a single line

Finally some_name;

and the call of foo() with

foo(some_name.data());

More generally, stop assuming that C++ works like Java. Both languages work differently. If you insist on using C++ constructors like you would in Java, you will write terribly buggy C++ code.

Peter
  • 35,646
  • 4
  • 32
  • 74