C++Builder 不会在 throw-catch-continue 上调用析构函数

C++Builder does not call destructor on throw-catch-continue

代码:

#include <stdio.h>

int ConstrCalls=0, DestrCalls=0;

struct Z
{
    Z() { ConstrCalls++; }
    ~Z() { DestrCalls++; }
};

int main(int argc, char**)
{
   bool Startup= true;

   do
   {
      Z z;

      try
      {
          if( Startup )
          {
              Startup= false;
              throw( 1 );
          }
          else
          {
              break;
          }
      }
      catch(int)
      {
          continue;
      }
   }
   while(true);

   printf( "ConstrCalls=%d DestrCalls=%d", ConstrCalls, DestrCalls);
   return 0;
}

C++Builder 能正常运行吗?

谢谢。

很遗憾...

the C++Builder 6, RAD Studio 2009 and XE7 Update 1, C++ compiler generates bad exception handling code (and in all likelihood all compilers in between--those are the compilers I current have access to). When an exception is thrown, the stack unwind code has been observed to:

  • Crash with an access violation
  • Fail to execute destructors when it should
  • Leak memory
  • Fire destructors twice

This makes it impossible to produce reliable, exception-safe, C++ software with this compiler.

查看 C++ compiler exception handling is completely broken 了解更多详情。

这来自“不在应该的时候触发析构函数”部分:

The following Button OnClick event handler constructs temporary Count objects only within the try/catch scope. Count objects keep track of the number of live instances in the count variable.

As an invariant the number of Count instances should be 0 following the try/catch. Instead this fails with BAD STACK UNWIND.

static int count = 0;

struct Count {
    Count() { ++count; }
    Count(const Count& rhs) { ++count; }
    ~Count( ) { --count; }
};

static int __fastcall destructorNotFired(int i=0, Count c=Count() ) {
    throw Exception( "DESTRUCTOR NOT FIRED" );
}

void __fastcall TExceptionBugTestForm::ButtonDestructorNotFiredClick(TObject *Sender)
{
    assert(count == 0);

    try {
        destructorNotFired( destructorNotFired() );
    } catch ( Exception& e ) {
    }

    if (count != 0) {
        ShowMessage( "BAD STACK UNWIND" );
    }

    assert(count == 0);
}

(与您的代码非常相似)。

异常处理在使用 clang++ 编译代码时效果很好(C++Builder 仅 64 位!= XE10)。