2010-08-13 148 views
8

我正在使用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失败。

请帮我解决这个问题。

+0

使用四个空格缩进代码,而不使用正常文本。 – 2010-08-13 09:07:01

+1

您是否使用相同的C++运行库构建了exe和DLL? – Mark 2010-08-13 09:09:43

+0

是的,我建立了与Visual Studio。只有配置类型不同。一个是exe,另一个是Project配置中的DLL配置。 – bjskishore123 2010-08-13 09:13:59

回答

4

确保您使用相同的运行时构建僵尸程序EXE和DLL,最好是使用动态运行时。

+0

崩溃通过在exe和dll中使用相同的运行时库来解决。谢谢大家帮助我。 – bjskishore123 2010-08-13 09:34:27

1

它在析构函数中崩溃,析构函数正在调用terminate和crash应用程序时抛出一个异常。 Uncaught exceptions

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

+0

全局对象在main()被调用之前正在构建。 所以我认为,它的破坏发生在main()退出后。 那时,STL内部使用的列表 sourceList头在释放时无效。因此CrtIsValidHeapPointer失败。 – bjskishore123 2010-08-13 09:15:50

+0

现在的问题是:为什么sourceList头是无效的?如果您的exe和DLL使用兼容的运行时正确构建,那么此代码应该可以正常工作。运行时将在释放堆之前清理全局对象。 – 2010-08-13 09:23:37

+0

崩溃是通过在exe和dll中使用相同的运行时库来解决的。 谢谢大家的帮助。 – bjskishore123 2010-08-13 09:31:17

1

全局对象被初始化并被C运行时。它们在main被调用并在其返回之后被初始化。

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

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

+0

我没有添加任何节点到sourceList(列表)。 析构函数调用时列表为空。 但是,STL List在内部仍然会有一个隐藏的Head指针。当试图释放它,它崩溃。 – bjskishore123 2010-08-13 09:20:30

+0

您正在构建EXE和DLL的哪个CRT? – 2010-08-13 09:25:11

0

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

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检测。

* 对于拥有标准库实现

+0

'+ 1'从我这个全面的答案。 @ bjskishore123:请阅读[FAQ](http://stackoverflow.com/faq)。我们鼓励你接受你最能帮助你解决问题的答案。 – sbi 2010-08-13 16:30:10

0

尝试的任何效果,使您的构造函数和析构函数非内联,它可以帮助所有的预处理器标志。如果ctor和dtor不是内联的,则两者都将以dll的名义生成,因此将使用相同的运行时库执行列表<>的构建和销毁。 通常,尽量避免通过dll边界传递不透明的stl对象。最好将它们作为privatte成员封装到您自己的类中,并提供非内联方法来操作此类成员