繁体   English   中英

堆栈展开失败的原因

[英]Reasons for stack unwinding fail

我正在调试一个应用程序并遇到以下代码:

int Func()
{

 try 
 {

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

}

m_CriticalSection 是 CCrialSection。

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

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

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

3) 我可以通过将 CSingleLock 放在 try 块之外来解决这个问题吗?

谢谢,

您是否遇到程序异常终止?

我相信你的CCriticalSection object 会释放CSingleLock的析构函数。 析构函数将始终被调用,因为这是堆栈上的 object。 当用户代码抛出时,function 中throw和捕获之间的所有堆栈都将被解除。

但是,您的用户代码中的其他一些 object 甚至CSingleLock析构函数可能同时引发了另一个异常。 在这种情况下, m_CriticalSection object 将无法正确释放,并且调用std::terminate并且您的程序终止。

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

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;
    }
}

为了清楚起见,请阅读常见问题解答。

我可以通过将 CSingleLock 放在 try 块之外来解决这个问题吗?

如果不查看堆栈和错误/崩溃,很难说。 你为什么不试一试。 它还可能通过隐藏真正的问题来引入一个微妙的错误。

首先让我说我不知道 CSingleLock 和 CCriticalSection 是做什么的。

unwind the stack and destroy any variables that were created within the try { } block.我所知道的是,在“用户代码”部分中引发的异常展开堆栈并破坏在 try { } 块中创建的任何变量。

在我看来,我希望您的 aLock 变量会被异常破坏,而不是 m_CriticalSection。 您正在将指向 m_CriticalSection 的指针传递给 aLock 变量,但 m_CriticalSection object 已经存在,并且是在其他地方创建的。

  • 你确定你的 m_CriticalSection 的生命周期比 CSingleLock 长吗?
  • 也许有人破坏了你的堆栈?
  • 3) 我可以通过将 CSingleLock 放在 try 块之外来解决这个问题吗?

    在这种情况下 - 是的。 但是请记住,将大块放入互斥锁中对性能不利。

  • 顺便说一句,catch(...) 通常不是一个好习惯。 在 Win32 中,它 (catch(...)) 也捕获 SEH 异常,不仅是 c++ 异常。 也许你在这个 function 中有核心并用 catch(...) 捕获它。

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

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

  • throw 表达式的构造函数抛出异常
  • 异常传播时从析构函数抛出异常。
  • 抛出的异常从未被捕获(如果这实际上展开堆栈,则定义实现)。
  • 异常规范中未指定的异常抛出。
  • C ABI 引发异常。
  • 在未捕获的线程内抛出异常(实现定义了发生的情况)

3) 我可以通过将 CSingleLock 放在 try 块之外来解决这个问题吗?

不会。以上所有情况都会导致应用程序终止,而无需进一步展开堆栈。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM