[cfe-dev] [Bug] Wrong Exception Handling : Destructor not called immediately

Matthew Del Buono mpdelbuono at gmail.com
Fri Apr 4 10:55:36 PDT 2014


I think the test case looks correct but my analysis is inconsistent with
yours. However I agree there is a bug. Interestingly, while looking into it
just now I wrote my own test case which revealed a separate (but perhaps
related) bug in an old version of g++ (4.1.2) where destructors were being
called twice. The current version appears to be correct though. Anyway, my
test case follows:

#include <iostream>
class Foo
{
private:
   static int n;
   static bool thrown;
   int m_n;
public:
   Foo():m_n(n++) { std::cout << "Constructor " << m_n << std::endl; }
   ~Foo() noexcept(false) { std::cout << "Destructor " << m_n << std::endl;
      if(!thrown) {
         thrown = true;
         std::cout << "Throwing exception" << std::endl;
         throw 0;
      }
   }
};

int Foo::n = 0;
bool Foo::thrown = false;

Foo bar(Foo a, Foo b) { return Foo(); }

int main()
{
   try
   {
      Foo foo = bar(Foo(), Foo());
   }
   catch(...)
   {
      std::cout << "In exception handler" << std::endl;
   }
   std::cout << "Out of exception handler" << std::endl;
}


I expect the following output:

Constructor 0
Constructor 1
Constructor 2
Destructor 1
Throwing exception
Destructor 2
Destructor 0
In exception handler
Out of exception handler


With clang++ 3.4 I'm getting the following output:

Constructor 0

Constructor 1

Constructor 2

Destructor 1

Throwing exception

Destructor 0

In exception handler

Out of exception handler



So it looks like the destructor for the returned object is not being
called at all (not in the wrong order). I get the same behavior in
C++11 mode, too (though you have to add noexcept(false) to the
destructor due to the implicit noexcept).


-- Matthew P. Del Buono



On Fri, Apr 4, 2014 at 9:39 AM, suyog sarda <sardask01 at gmail.com> wrote:

> Gentle Ping !! Please help to verify if this is a bug and if my analysis
> is correct.
>
>
> On Tue, Apr 1, 2014 at 10:18 PM, suyog sarda <sardask01 at gmail.com> wrote:
>
>> Hi all,
>>
>> This is a test g++ test case for checking correct exception handling.
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> *#ifdef __GXX_EXPERIMENTAL_CXX0X__#define NOEXCEPT_FALSE noexcept
>> (false)#else #define NOEXCEPT_FALSE#endifextern "C" void abort (); int
>> thrown;int as;struct a {  a () { ++as; }  ~a () NOEXCEPT_FALSE { --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 ();} *
>>
>> This Test Case aborts on ARM as well as X86 with clang latest trunk while
>> with g++ no aborts are seen .
>>
>> Here, when first temporary object '*a'* gets destroyed, its destructor
>> is called where we throw an exception. This should immediately call
>> destructor of *'b'* and before calling constructor of second temporary
>> object *'a'*. Instead, with clang, it is waiting for second temporary
>> object *'a'* to get destroyed and then calling its own destructor.
>>
>> In my opinion, the compiler is not generating correct landing pad for the
>> exception. Can someone please help in validating this reason? If it is a
>> genuine bug then i will file a bug and try to work out solution for it.
>>
>> --
>> With regards,
>> Suyog Sarda
>>
>
>
>
> --
> With regards,
> Suyog Sarda
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20140404/089e4245/attachment.html>


More information about the cfe-dev mailing list