析构函数崩溃

时间:2010-08-13 09:04:25

标签: c++ destructor

我正在使用Visual Studio中的Win32 c ++应用程序。

在其中一个源文件中,我有如下的全局对象。

TestClass tObj;

int main() //Execution starts here
{
}

TestClass在下面的其他DLL中定义。

struct Source
{

};

class TestClass
{
  list<Source> sourceList;
    public:
         TestClass() {}
        ~TestClass() {}
};

当我的应用程序运行时,如果我尝试显式关闭应用程序, 通过关闭控制台窗口,它在TestClass析构函数中崩溃。 Callstack显示CrtIsValidHeapPointer失败。

请帮助我解决这个问题。

6 个答案:

答案 0 :(得分:9)

您的问题是.exe和.dll之间不同的编译器/链接器设置有效地导致.dll和.exe使用标准库的不同实现:

  • 您必须使用相同的预处理程序标志*来构建.exe和.dll,否则每个二进制文件将使用略有不同的实现进行编译。
  • 您必须将.exe和.dll都链接到动态运行时。静态链接到运行时的二进制文件获取自己的堆 - 最终在一个堆上分配并尝试在另一个堆上释放。

要解决此问题,请转到Project > Properties > Configuration Properties > C/C++ > Code Generation并将运行时库选项更改为Multi-threaded Debug DLL (/MDd)。您必须为.exe项目和.dll项目执行此操作。

从Visual Studio 2010开始,使用#pragma detect_mismatch会在链接时检测到某些错误。

* 对于所有对标准库实现有任何影响的预处理器标志

答案 1 :(得分:4)

确保使用相同的运行时构建机器人EXE和DLL,最好使用动态运行时。

答案 2 :(得分:1)

它在析构函数中崩溃,从析构函数抛出异常,该析构函数调用terminate并使应用程序崩溃。Uncaught exceptions

  

有两种情况可以调用析构函数。第一种是在“正常”条件下销毁对象,例如,当它超出范围或被明确删除时。第二种是在异常传播的堆栈展开部分期间异常处理机制破坏对象。您必须在保守的假设下编写析构函数,因为如果控件在另一个异常处于活动状态时因异常而离开析构函数,则C ++将调用终止函数

答案 3 :(得分:1)

全局对象由C运行时初始化和销毁​​。它们在main被调用之前被初始化,并在它返回后被销毁。

错误可能是由TestClass析构函数(或间接来自Source析构函数)访问的内容引起的。析构函数代码正在访问无效内存(或已释放的内存)。

未定义全局变量的初始化和销毁​​顺序,并且经常是应用程序终止时的错误源。如果有其他全局变量可能会清理或修改TestClass引用的资源,那么这可能是罪魁祸首。

答案 4 :(得分:0)

使用相同的对齐(pack pragma)构建DLL和EXE吗?

答案 5 :(得分:0)

尝试使你的构造函数和析构函数非内联,这可能会有所帮助。如果ctor和dtor不是内联的,则两者都将代表dll生成,因此构造和销毁列表&lt;&gt;将使用相同的运行时库执行。 通常,尽量避免跨越dll边界传递不透明的stl对象。最好将它们作为私有成员封装到您自己的类中,并提供非内联方法来操纵这些成员