描述并找到一个破坏状态的错误,导致看似随机的崩溃

时间:2011-08-22 23:45:46

标签: c++ debugging

我目前正面临着我在团队正在开展的大型复杂项目中遇到过的最邪恶的错误之一。我们使用C ++作为编程语言,目前使用Visual Studio进行开发,尽管最终产品旨在跨平台运行。

错误:

我们的系统中存在一个错误,它会在看似随机的执行点触发崩溃。崩溃原因通常是对每次执行程序时更改的地址的读取访问冲突。有时我们也会遇到堆损坏错误。调用堆栈引导我们在代码库中使用变量点,很少使用一些外部库(在我们的例子中为Lua),其中的错误显然不存在。

好像这个bug在过去的4个月里一直在发展。大概一段时间以前,我的一些团队成员看到前端程序在方式和位置上的崩溃与现在发生的情况非常相似。

更多细节:

我们的代码库大约有800K行的纯C ++(评论除外)很大,并且是在3年的时间里开发出来的。 目前的项目重约300K。我们之前使用了过多的单元测试和其他方法来消除错误,如断言,智能指针等。

其他人和我一直试图找到这个错误超过2周。对我来说,这不仅仅是一场噩梦。在这样一个复杂的项目中,即使是好的旧版printf调试也无法面对现在的复杂性。

我的问题

  • 我们在这里遇到什么样的错误?有没有这个名字?这种错误是否会在其他大型项目中或多或少地发生?

  • 在各种平台和各种构建设置上使用各种实用工具进行了2周的无果力调试后,我们可以做些什么来找到并消除它?

(我之前的问题已经结束,所以我这次尝试更好地制定它并提供更多详细信息,链接:https://stackoverflow.com/questions/7154645/how-is-this-kind-of-bug-called

2 个答案:

答案 0 :(得分:8)

您描述的症状是典型的堆损坏(并非所有堆损坏都会报告错误消息!)。您需要审核程序中所有对象的生命周期;确保你没有释放两次东西,或者在释放它们之后使用它们,并确保你没有溢出任何缓冲区。您可能希望借此机会使用std::smart_ptr(或boost::smart_ptr)等内容来自动执行堆管理的各个部分。

如果您使用的是Linux或Mac OS,请尝试在valgrind下运行程序 - 它会检测到许多堆和堆栈损坏错误。在Windows上,使用application verifier;它可以帮助使错误导致崩溃更接近它们真正发生的时间点。

如果您正在使用线程,则导致堆损坏的竞争条件是另一种可能性。审核您的锁定机制。

如果您可以轻松地重现此错误,并且有一个源控制系统,请考虑二分法以确定它何时被引入。也就是说,对源代码历史记录执行二进制搜索,以找到第一个带有bug的提交。 Git有一个自动执行此操作的工具 - git-bisect - 如果您还没有使用git,可以将存储库的副本导入git以运行此工具。

另外,看看是否可以禁用程序的某些部分(防止有问题的代码被调用)以尝试缩小问题范围。请注意,这可能有误报 - 如果您禁用模块X并且它停止崩溃,则可能意味着模块X正在破坏堆,或者它可能意味着模块W损坏了堆并且模块X恰好擅长注意到它

答案 1 :(得分:0)

只是补充Bdonlan的优秀答案:既然您正在为Windows开发代码并处理大型项目,我强烈建议您购买“高级Windows调试”一书并熟悉WinDbg,AppVerifier和其他类似工具。这非常值得投资。 在本书中,整章都专门讨论堆损坏(正如前面的答案中已经提到的),很可能是你所面临的问题。