0

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?

Coder12345
  • 3,431
  • 3
  • 33
  • 73
  • 2
    This happens also on C++Builder XE5, FWIW. – Rodrigo Gómez Nov 21 '14 at 20:42
  • 3
    This same issue was discussed yesterday in the Embarcadero forum, where I provided an analysis of what the compiler is doing: [Why is UnicodeString losing scope in this example?](https://forums.embarcadero.com/thread.jspa?threadID=110377). – Remy Lebeau Nov 21 '14 at 23:48
  • Stack unwinding has always been buggy in bcc32; e.g. [this bug](http://stackoverflow.com/a/27117266/1505939) has been around for donkey's years and is still present – M.M Nov 27 '14 at 02:51

2 Answers2

3

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.

Tracer
  • 2,544
  • 2
  • 23
  • 58
  • Thanks for investigating this. It seems this is a bug in C++ Builder 2010 as the variable should still stay in scope as it happens for vectors too. I will use workaround solutions. – Coder12345 Nov 21 '14 at 18:42
  • The memory allocated by `new` is never `delete`d in this code, causing a memory leak. I guess `delete test;` should actually be inside the `__finally` block. – M.M Nov 27 '14 at 02:39
  • Also it's not clear to me whether C++Builder guarantees that `test` still retains its same pointer value in this case (perhaps Remy would know) – M.M Nov 27 '14 at 02:49
1

(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.

M.M
  • 138,810
  • 21
  • 208
  • 365