我正在调试应用程序并遇到以下代码:
int Func()
{
try
{
CSingleLock aLock(&m_CriticalSection, TRUE);
{
//user code
}
}
catch(...)
{
//exception handling
}
return -1;
}
m_CriticalSection是CCricialSection。
我发现用户代码抛出异常,导致m_CriticalSection根本没有释放。这意味着由于某些原因,堆栈已损坏,因此展开失败。
我的问题是: 1)在什么不同的情况下,堆栈展开会失败?
2)可以抛出异常的不同可能性,使堆栈展开失败。
3)我可以通过将CSingleLock放在try块之外来解决这个问题吗?
谢谢,
答案 0 :(得分:2)
您是否收到异常程序终止?
我相信你的CCriticalSection
对象将被释放CSingleLock
的析构函数。析构函数将始终被调用,因为它是堆栈中的对象。当用户代码抛出时,函数中throw
和catch之间的所有堆栈都将被展开。
但是,在此期间,您的用户代码中的某些其他对象甚至CSingleLock
析构函数可能会抛出另一个异常。在这种情况下,m_CriticalSection
对象将无法正常释放,并且std::terminate
被调用并且您的程序将死亡。
以下是一些示例。注意:我使用std::terminate
处理函数来通知我状态。您还可以使用std::uncaught_exception
查看是否存在未捕获的异常。这个here上有一个很好的讨论和示例代码。
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;
}
}
为了清晰起见,请阅读this常见问题解答。
我可以通过将CSingleLock放在try块之外来解决这个问题吗?
很难说没有看看堆栈和错误/崩溃。你为什么不试一试。它还可能通过隐藏真正的问题来引入一个微妙的错误。
答案 1 :(得分:0)
首先让我说我不知道CSingleLock和CCriticalSection做了什么。
我所知道的是,“用户代码”部分中抛出的异常应该展开堆栈并销毁在try {}块中创建的所有变量。
在我看来,我希望你的aLock变量被异常破坏,但不会被m_CriticalSection破坏。您正在将指向m_CriticalSection的指针传递给aLock变量,但m_CriticalSection对象已存在,并且已在其他位置创建。
答案 2 :(得分:0)
3)我可以通过将CSingleLock放在try块之外来解决这个问题吗?
在这种情况下 - 是的。但请记住,将大块放在互斥锁中对性能来说并不是一件好事。
顺便说一下,捕捉(......)一般不是好习惯。在Win32中它(catch(...))也捕获SEH异常,而不仅仅是c ++异常。也许你在这个函数中有核心并用catch(...)来捕获它。
答案 3 :(得分:0)
我的问题是:
1)在什么不同的情况下,堆栈展开会失败?
如果exit()terminate()调用abort()或者unexpected()。
2)可以抛出异常的不同可能性,使堆栈展开失败。
3)我可以通过将CSingleLock放在try块之外来解决这个问题吗?
没有。所有这些导致应用程序终止而不进一步展开堆栈。