【发布时间】:2021-12-26 09:59:35
【问题描述】:
基本上情况是我们有一个 C++ 程序在尝试访问一个已经释放的对象时偶尔会崩溃(在 Debug 构建中,我们注意到指向的内存充满了通常的“cdcdcdcd”模式)。我们试图跟踪清除对象的每个点,但找不到已知指针未正确设置为 null 的位置。
有两个主要问题 - 代码非常庞大且令人费解,编写了至少十年的时间,并且有几个开发人员下落不明,甚至有些人已经去世,因此无法进入与最初编写代码的人联系。代码的复杂性使得手动确定存在多少指向所述对象的指针以及哪些函数使用或复制它们是不切实际的。
第二个大问题是我们没有可靠的重现方式。我们知道,在拥有数百个并发用户的生产系统中,它每天大约崩溃两次,但在测试环境中重现崩溃的所有尝试都失败了。我们应该可以在崩溃后检查生产环境几分钟,但最终我们必须将其恢复。环境为Windows Server 2019,程序用Visual Studio 2019编译,服务器上有Visual Studio的副本和程序源代码。我们已经尝试使用 DMP 文件,但失败了,因为转储只显示了悬空指针的使用,它没有告诉我们指向的对象被释放的点在哪里。
我会很感激任何建议,因为我几乎没有想法。
谢谢。
【问题讨论】:
-
我会从寻找Rule of Three 违规者开始。
-
没有minimal reproducible example,我们无能为力。将原始指针使用替换为
shared_ptr或unique_ptr可能会解决此问题。您可以将打印语句添加到导致崩溃的对象的析构函数并打印其地址,甚至可能是堆栈跟踪。编写大量单元测试并使用测试覆盖工具来确保他们在夜间测试所有内容也有帮助 -
对象及其类型,甚至事后访问它的位置都是已知的。现在通常是繁琐的工作来确定您用来取消引用它的指针是从哪里复制的,而其他副本是从哪里删除的。如果您的团队中没有人可以,那么您必须雇用。
-
我将不胜感激任何建议,因为我几乎没有想法。 -- 缓慢但肯定地重写可以使用现代 C++ 重写的代码部分容器、智能指针、
std::string而不是字符指针等,并观察新程序是否正确运行。如果新程序模仿了旧程序,而新程序崩溃了,那么您现在有更好的机会来调试问题。 -
MSVS 现在支持 Address Sanitizer 。首先使用它构建一个发布版本并对其进行测试。确保还为任何转储分析生成必要的 .pdb 文件。
标签: c++ visual-studio pointers debugging dangling-pointer