Windows应用程序因纯虚函数调用而崩溃

Posted

技术标签:

【中文标题】Windows应用程序因纯虚函数调用而崩溃【英文标题】:windows application crashing with pure virtual function call 【发布时间】:2011-04-18 16:51:17 【问题描述】:

我有一个 Windows 应用程序,它时不时地崩溃,而且不会重现。 当它发生时,我会调用纯虚函数。我已将其设置为使用 ADplus 创建 Windows 转储,即使它崩溃,也永远不会有转储。

我很确定这是构建错误,我正在使用 VC2008 SP1 构建,这是发布版本。

对此有何见解?我该如何调试它,它是一个带有 .pdb 文件和映射文件的发布版本。

谢谢 雷扎

【问题讨论】:

【参考方案1】:

正如已经指出的那样,这不太可能是构建错误。我有一个非常复杂的项目,有一个类似的问题,并且能够通过使用_set_purecall_handler 并提供我自己的处理程序来追踪它。这样我就能够在它发生时闯入调试器并查看调用堆栈。显然,这里的另一种选择是在它发生时创建小型转储。请记住,您需要在程序遇到异常之前为小型转储做好一切准备。

但是,这也很有可能是由堆损坏引起的。不过,在这种情况下,我预计会出现各种症状。你描述了这个特定的症状,所以很可能你的代码确实有问题。

我上面提到的项目是一个遗留项目,它模拟了类似于 COM 的东西,确实有些地方编译器不可能找到所有在派生类中不存在实现的纯虚函数。

【讨论】:

当你说为小型转储准备一切时,有什么办法? @reza: 确保 dbghelp.dll 已加载并且所有函数指针已被检索(顺便说一句,不加载它是没有创建转储文件的最常见原因 - 通常是因为没有最新版本的DLL 存在于系统中)。另外,为它准备一个名字。当应用程序“悬空”(即不稳定)时,您尝试的任何和所有操作都可能是致命的。因此,请尝试在调用异常处理程序或纯虚函数处理程序并创建转储文件之前执行所有相关操作。【参考方案2】:

首先,确保您不是calling pure virtual function。如果不是这种情况,请尝试在WinDbg 下启动您的程序。

【讨论】:

这是一个 NT 服务,我该怎么做? @reza,这是答案:How to debug Windows services【参考方案3】:

我很确定这是构建错误

非常非常可能。这更有可能是您的代码中的错误。

你可能在某个地方是slicing an object。如果您的应用设置为在 unhanded exceptions 上生成转储文件,但您仍然没有转储文件而死机,那么错误很可能在异常处理程序中。

您需要获取转储文件。这应该是您的首要任务。

【讨论】:

【参考方案4】:

如果您的问题不是恒定的,则很可能存在索引写入不足的问题,这可能会损坏内存

【讨论】:

“我认为您无法调试发布版本。”当然可以。你为什么会这样想? 如何调试发布版本,我有 pdb 文件和映射文件。【参考方案5】:

如果您尝试过完全重建,那么它似乎更有可能是编码问题。

您是否在任何构造函数或析构函数中调用任何(纯)虚函数?

更有可能是您在已删除对象上调用纯虚函数,并且 vtable 已被移动以指向父对象。在这种情况下 valgrind (free, linux) 或 Purify ($$$, Windows) 真的可以帮助你。 VS 可能也有内存检查器。

【讨论】:

如果应用程序的构建方式允许堆检查器查看问题,则应用程序验证程序可以提供帮助。 什么是应用验证器?【参考方案6】:

我曾经在使用 C++ 时遇到过类似的问题。我在某处从构造函数调用了虚函数,因此调用发生时对象尚未构造,解释了调用的“纯”虚函数。如果您对对象而不是指向对象的指针有错误的强制转换,这也可能是 slicing 的问题。使用调试器并逐步/回溯查找源代码,以便我们更好地为您提供帮助。

【讨论】:

【参考方案7】:

我有同样的错误。我多次查看代码,从未发现在构造函数或析构函数中使用虚函数。 问题出在构建系统中。我的计算机上有旧的静态库版本,其中某些功能不是纯虚拟的,当它变成新的时(我又添加了一个抽象层)。因为EXE文件是用旧的静态库创建的,但是新的头文件,出现了这个错误。 因此,如果没有其他帮助,请确保您的库和包含文件版本一致。

【讨论】:

以上是关于Windows应用程序因纯虚函数调用而崩溃的主要内容,如果未能解决你的问题,请参考以下文章

纯虚函数调用

虚析构函数与纯虚函数

如何解决“调用纯虚方法”

C++ 纯虚函数

在 C# 中处理纯虚函数调用

抑制消息框 R6025 纯虚函数调用