[cfe-dev] [LLVMdev] [LLVMDev] Object in a try-catch block not being destroyed even after an exception

Joshua Cranmer pidgeot18 at gmail.com
Tue Jun 19 12:19:48 PDT 2012


On 6/19/2012 7:14 AM, SHIVA PRASAD wrote:
> Dear LLVM Members,
>
>         The below source code from gcc test suite replicates the 
> problem which i am facing.  When it is built with clang, it throws an 
> abort(highlighted).
> The following are my observations -
>
> 1. The object(tmp) is not getting destroyed immediately after the 
> exception is thrown.  In case of Clang, the object is getting 
> destroyed at a later point of time.
> 2. In case of gcc, the scope of the object created inside the 
> try-catch block is limited to the block.  Once the exception is 
> thrown, the object(tmp) is destroyed.
> 3. The assembly files for both clang and gcc were generated and 
> compared, wherein the sequence of operations look similar.
> 4. I also tried the MS-Visual Studio compiler, which gives a result 
> similar to gcc.

This looks specific to clang, not to LLVM, so moving to cfe-dev.

[Source code below not elided for anyone on cfe-dev who isn't on 
llvmdev; I have more comments trailing, so scroll down].
> As per my understanding of the C++ standard, the object has to be 
> destroyed as soon as the exception is thrown.
> Please let me know which is the correct behavior and suggest me the 
> changes required.
>
>
> Thanks & Regards,
> Shivaprasad
> shivahms at gmail.com <mailto:shivahms at gmail.com>
>
> /******************************************************************Source 
> Code 
> Start*******************************************************************/
> extern "C" void abort ();
>
> int thrown;
>
> int as;
> struct a {
>   a () { ++as; }
>   ~a () { --as; if (thrown++ == 0) throw 42; }
> };
>
> int f (a const&) { return 1; }
> int f (a const&, a const&) { return 1; }
>
> int bs;
> int as_sav;
> struct b {
>   b (...) { ++bs; }
>   ~b ()   { --bs; as_sav = as; }
> };
>
> bool p;
> void g()
> {
>   if (p) throw 42;
> }
>
> int main () {
>   thrown = 0;
>   try {
>     b tmp(f (a(), a()));
>
>     g();
>   }
>   catch (...) {}
>
>   // We throw when the first a is destroyed, which should destroy b before
>   // the other a.
>   if (as_sav != 1)
> abort ();
>
>   thrown = 0;
>   try {
>     b tmp(f (a()));
>
>     g();
>   }
>   catch (...) {}
>
>   if (bs != 0)
>     abort ();
> }
> /******************************************************************Source 
> Code 
> End*******************************************************************/
>

What clang is generating can be approximated by the following pseudocode:
atmp1, atmp2, btmp = alloca space for temporaries
call a::a on atmp1
try {
   call a::a on atmp2
   try {
     call f(atmp1, atmp2)
     call b::b on btmp
   } catch {
   } finally {
     call a::~a on atmp2
   }
} catch {
} finally {
   call a::~a on atmp1
}
// NOW b is "constructed"

Looking at the output IR, the best interpretation I can give is that 
Clang is cleaning up the temporary arguments before calling the new 
variable constructed. The question, of course, is whether or not this is 
legal per the C++ spec. C++11 section 12.2, par 3 states that
> Temporary objects are destroyed as the last step
> in evaluating the full-expression (1.9) that (lexically) contains the 
> point where they were created.

Section 1.9, par 10 has an example which states that the full expression 
associated with the call to the constructor in this case is indeed the 
actual constructor call.

Section 15.2, par 1 states:
> As control passes from a throw-expression to a handler, destructors 
> are invoked for all automatic objects
> constructed since the try block was entered. The automatic objects are 
> destroyed in the reverse order of the
> completion of their construction.

I'm not 100% what the correct interpretation is in this case. It comes 
down to whether b should be considered constructed before or after the 
full expression of the declarator is completed.

-- 
Joshua Cranmer
News submodule owner
DXR coauthor

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20120619/767f196e/attachment.html>


More information about the cfe-dev mailing list