__finally in C++ Builder 2010 losing scope?

853 views Asked by At

Here is a very strange thing which I don't think should happen:

UnicodeString test = "abc";

try
    {
    try
        {
        int a = 123;
        return a;   // This seems to produce a problem with "test" variable scope
        }
    catch (Exception &e)
        {
        // Some exception handler here
        }
    }
__finally
    {
    // At this point the "test" variable should still be in scope???
    test = "xyz"; // PROBLEM here - test is NULL instead of "abc"! Why?
    }

If I remove the return a; in the try-catch block the test variable is still defined. Is there a particular reason why after the above construct the UnicodeString seems to go out of scope? Is it a bug with C++ Builder 2010? I understand that return returns from function but it should still retain variable scope in the __finally block shouldn't it?

2

There are 2 answers

3
Tracer On BEST ANSWER

I did a bit more analysis and it seams that once you execute return statement all local objects from stack are acting as destroyed. If you try using heap objects instead this won't happen.

UnicodeString *test = new UnicodeString("abc");

try
    {
    try
        {
         int a = 123;
        return a;   // This seems to produce a problem with "test" variable scope
        }
    catch (Exception &e)
        {
        // Some exception handler here
        }
    }
__finally
    {
    ShowMessage(*test); // "abc" 
    *test = "xyz"; 
    }
delete test;

Using smart pointers like unique_ptr will again result in loosing an object in __finally since return will initiate it's destruction.

0
M.M On

(Remy posted this in comments but did not post an answer here)

When a return statement is hit within a try...finally block, what happens is that any local objects are destroyed (as they would be for any other return) before the __finally block is entered.

So by the time your code gets up to test = "xyz";, test has already been destroyed, causing undefined behaviour.

I guess it is a matter of semantics whether you call this a bug or a design flaw, but either way it is something to bear in mind when using try...finally. My personal advice would be to just not use it at all; the Standard C++ techniques of try...catch and RAII can solve any problem.