抛出例外时未执行(没有堆栈放松)的破坏者
Destructors not executed (no stack unwinding) when exception is thrown
我发现了一个非常奇怪的行为,我从未见过。我正在研究一个复杂的VS2005 C 项目。
class Tester
{
public:
Tester()
{
TRACE("Construct Tester");
}
~Tester()
{
TRACE("~Destruct Tester");
}
};
void Thrower()
{
Tester X;
throw std::exception("Booom");
}
当调用Thrower()
时,您期望在跟踪输出中看到什么?该测试仪在堆栈被解开时被构造,然后破坏?
至少我期望这一点,但是测试仪的破坏者从未被称为!
不可能!?!?!?!
这是Visual Studio中的错误?
我搜索了很多,但甚至没有在stackoverflow上找到答案。
我花了整整一天的时间来找出出了什么问题。
现在,我必须更深入地解释自己在做什么。我有一个C 代码,该代码将其编译到LIB文件中。上面的代码(测试仪和投掷器)位于此普通的C LIB文件中。
我还有另一个C 代码,该代码将其编译到托管的C DLL中,该代码与此LIB文件链接在一起。因此,最后两个代码都在同一dll中。我管理了包装器功能,这些功能会在这样的LIB文件中调用代码:
ManagedWrapper()
{
try
{
Thrower();
}
catch (std::exception& e)
{
throw new System::Exception(e.what());
}
}
这确实不工作。使用此代码,我有不关闭的内存泄漏和网络插座。投掷器中的堆栈没有解开。
这样做的原因是,在达到捕获之前不会发生堆栈。但是,当Catch坐在另一个图书馆中,而不是投掷堆栈就不会解开。DLL不知道如何在LIB文件中放松堆栈(尽管两者最终都被编译到同一DLL中!!)
,但我找到了一个非常简单的解决方案。
在lib文件中,我必须在theedwrapper()和类似的throter()之间添加一个中间功能。该代码看起来很愚蠢,但它解决了问题:
Catcher()
{
try
{
Thrower();
}
catch(...) // unwind HERE
{
throw;
}
}
重要的是,该捕捉器必须坐在抛出异常的自由文件中。当捕获异常时,堆栈将解开,然后将异常重新插入托管包装器。
有时看起来很愚蠢的代码非常聪明!
摘要:永远不要忘记,必须始终将异常捕获在它们被扔的同一库中。如果它们越过图书馆边界,您会有严重的问题。
- 算法问题:查找从堆栈中弹出的所有序列
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- Visual Studio(或任何其他工具)能否将地址解释为调用堆栈(boost上下文)的开头
- 为什么调用堆栈数组会导致内存泄漏
- gdb错误:Backtrace已停止:上一帧与此帧相同(堆栈已损坏?)
- 在 leetcode 上提交解决方案时出现堆栈缓冲区溢出错误
- 我的 int main() 中出现堆栈溢出错误
- 堆栈和队列是否像C++中的数组一样传递?
- 拥有映射的现代方法,该映射可以指向或引用已在堆栈上分配的不同类型的数据
- 为什么 STL 容器适配器堆栈中的 top 返回常量引用?
- 从堆栈分配的原始指针构造智能指针
- 在函数范围内在堆栈上分配的数组在离开函数时是否总是被释放?
- 堆栈中大小变量输入错误 (C++)
- 堆栈问题(平衡表达式问题集)
- C++ 在堆栈中包含多态属性的类对象存储
- 用于解析 win64 堆栈跟踪的命令行客户端(可以访问符号服务器)
- 在 C++ 中使用链表进行堆栈
- 变量周围的堆栈'...'已损坏
- 在 gtest 中初始化堆栈上的引用变量的隔离错误
- 抛出例外时未执行(没有堆栈放松)的破坏者