2011-08-22 51 views
5

我目前正面临着我的团队正在处理的大型复杂项目中遇到的最恶毒的错误之一。我们使用C++作为编程语言,目前使用Visual Studio进行开发,尽管最终产品旨在运行跨平台。描述并发现导致看似随机崩溃的状态腐蚀问题

的错误:

有一个在我们的系统在执行看似随机点触发崩溃的错误。崩溃原因通常是每次执行程序时都会更改的地址读访问冲突。有时我们也会收到堆损坏错误。调用堆栈导致我们在代码库中发生变化,而很少发生到某些外部库(我们的例子中是Lua),这些错误显然不在此处。

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

更多的细节:

我们的代码库是纯C的大约800K行++(注释除外)大,超过3年的课程开发。目前的项目重约30万。我们已经使用了过多的单元测试和其他方法来消除错误,例如断言,智能指针等。

其他人和我一直在试图找到这个bug超过2个星期了。这对我来说已经不仅仅是一场噩梦。在这样一个复杂的项目中,即使是旧的printf调试,在面对现在复杂的情况下似乎也会失败。

我的问题

  • 在我们这里面临什么样的错误呢?甚至有这个名字吗?这种错误在其他大型项目中多多少少出现过?

  • 在使用各种实用程序,在各种平台和各种构建设置上花费了2个星期的无果调试之后,我们可以如何找到并消除它?

(我以前的问题被关闭,所以我想有更多的细节更好,制定这个时候,链接:https://stackoverflow.com/questions/7154645/how-is-this-kind-of-bug-called

+0

阿尔夫,零星的臭虫是最糟糕的。学习使用调试工具的时间。 –

回答

8

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

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

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

如果你可以很容易地重现这个错误,并且有一个源代码管理系统,考虑一个二等分来确定它是什么时候被引入的。也就是说,在您的源代码历史记录上执行二进制搜索以找到第一次提交错误。 Git有自动执行此操作的工具 - git-bisect - 如果您尚未使用git,则可以将库的副本导入到git中以运行此工具。

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

+1

非常好的一点。虽然请注意,平分零星的错误是非常困难的。 – Owen

+0

@Owen,因此“如果你可以很容易地重现”...:/ – bdonlan

+0

啊真的错过了。 – Owen

0

只是补充Bdonlan的外观极好的回答:因为你是为Windows开发代码,并与大项目的工作,我会强烈建议你买的“高级Windows调试”的书,用WinDbg中,AppVerifier的和其他类似的工具结识。这将是非常值得的投资。 在这本书中,整个章节专门讨论堆腐败问题,正如前面的回答中已经提到的那样,最可能是你面临的问题。