C++ 堆栈展开失败的原因

C++ 堆栈展开失败的原因,c++,winapi,mfc,C++,Winapi,Mfc,我在调试应用程序时遇到以下代码: int Func() { try { CSingleLock aLock(&m_CriticalSection, TRUE); { //user code } } catch(...) { //exception handling } return -1; } m_临界截面为C截面 我发现用户代码抛出了一个异常,使得m_CriticalSection根本没有发布。这意味着由于某些原因,堆栈已损

我在调试应用程序时遇到以下代码:

int Func()
{

 try 
 {

   CSingleLock aLock(&m_CriticalSection, TRUE);
   {
     //user code
   }
 }
 catch(...)
 {
     //exception handling
 }
 return -1;

}
m_临界截面为C截面

我发现用户代码抛出了一个异常,使得m_CriticalSection根本没有发布。这意味着由于某些原因,堆栈已损坏,因此展开失败

我的问题是: 1) 在哪些不同的情况下,堆栈展开可能会失败

2) 抛出异常的不同可能性会导致堆栈展开失败

3) 我可以通过将CSingleLock置于try块之外来解决此问题吗


谢谢,

您的程序是否异常终止

我相信您的
CCriticalSection
对象将被释放
CSingleLock
的析构函数。析构函数将始终被调用,因为它是堆栈上的一个对象。当用户代码抛出时,
抛出
和函数中的捕获之间的所有堆栈都将展开

但是,用户代码中的某些其他对象,甚至是
csingelock
析构函数,可能同时引发了另一个异常。在这种情况下,
m_CriticalSection
对象将无法正确释放,调用
std::terminate
,程序将死亡

这里有一些示例要演示。注意:我正在使用
std::terminate
处理程序函数通知我状态。您还可以使用
std::uncaught_异常
查看是否存在任何未捕获的异常。这里有一个很好的讨论和示例代码

结构{

首先,让我说我不知道CSingleLock和CCriticalSection做什么

我所知道的是,在“用户代码”部分抛出的异常应该释放堆栈并销毁try{}块中创建的任何变量

在我看来,我希望您的aLock变量被异常破坏,但不是m_CriticalSection。您正在将指向m_CriticalSection的指针传递给aLock变量,但m_CriticalSection对象已经存在,并且是在别处创建的。

  • 您确定m_CriticalSection的生存期比CSingelock更长吗
  • 也许有人破坏了你的堆栈
  • 3) 我可以通过将CSingleLock置于try块之外来解决此问题吗

    在这种情况下-是的。但请记住,在互斥中放入大数据块对性能不是一件好事

  • >p>w,catch(…)一般不是好的实践。在Win32中,它(catch(…))也会捕获SEH异常,这不仅是C++异常。
      我的问题是:
      1) 在哪些不同的情况下,堆栈展开可能会失败

      • 如果调用了exit()terminate()abort()或unexpected()

        • 除直接呼叫外,以下情况可能发生:
        • 将引发未处理的异常。(此处不适用)
      2) 抛出异常的不同可能性会导致堆栈展开失败

      • 从抛出表达式的构造函数中抛出异常
      • 异常传播时从析构函数引发的异常
      • 引发从未捕获的异常(如果这实际上是展开堆栈,则定义implementatin)
      • 引发异常规范中未指定的异常
      • 在C ABI上引发异常
      • 在未捕获的线程内引发的异常(实现定义了发生的情况)
      3) 我可以通过将CSingleLock置于try块之外来解决此问题吗


      否。以上所有操作都会导致应用程序终止,而不会进一步展开堆栈。

      如果您提到引发了哪种类型的异常,以及它是否在catch(…)中被捕获,则会有所帮助。为什么不将try…catch块放在用户代码周围呢?VC++catch(…)自VC++2005以来未捕获SEH异常。好消息和不错的补充:)
      struct S {
          S() { std::cout << __FUNCTION__ << std::endl; }
          ~S() { throw __FUNCTION__; std::cout << __FUNCTION__ << std::endl;  }
      };
      
      void func() {
          try {
              S s;
              {
                  throw 42;
              }
          } catch(int e) {            
               std::cout << "Exception: " << e << std::endl; 
          }
      }
      
      void rip() {
          std::cout << " help me, O mighty Lord!\n"; // pray
      }
      
      int main() {
          std::set_terminate(rip);
          try {
              func();
          }
          catch(char *se) {
              std::cout << "Exception: " << se << std::endl;
          }
      }