7

我在尝试追踪程序中的访问冲突时遇到了问题。它发生在第三次调用析构函数时,恰好在析构函数似乎完成时。

我花了几个小时试图追查这个问题,所以我正在寻找关于我可以做的事情的进一步建议。我正在使用newdelete运算符创建类实例。Visual Studio 输出窗口显示:

First-chance exception at 0x60e3ad84 (msvcp100d.dll) in WebCollationAgent.exe: 0xC0000005: Access violation writing location 0xabababab. Unhandled exception at 0x60e3ad84 (msvcp100d.dll) in WebCollationAgent.exe: 0xC0000005: Access violation writing location 0xabababab.

我能做些什么来尝试找出这些内存位置中的内容吗?

调用堆栈窗口显示以下内容(按照我将其粘贴到时间顺序的相反顺序,从最早到最新):

Program.exe!Network::`scalar deleting destructor'()  + 0x2b bytes   C++

Program.exe!std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >::~basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >()  Line 754 + 0xf bytes    C++

Program.exe!std::_String_val<wchar_t,std::allocator<wchar_t> >::~_String_val<wchar_t,std::allocator<wchar_t> >()  Line 478 + 0xb bytes  C++

msvcp100d.dll!std::_Container_base12::_Orphan_all() 第 214 行 + 0x5 字节 C++

我对此信息的最佳猜测是某种字符串变量导致了问题?有人对解释这些信息有什么建议吗?

任何其他建议也会很有用,在此先感谢。

我在 Windows 7 下编码并使用 Visual Studio 2010 Professional。

4

3 回答 3

4

在使用BoundsChecker(现在是 Borland DevPartner 的一部分)之前,我已经成功跟踪内存错误。有许多类似的产品也可能有所帮助:HeapAgentRational Purify。这些看起来很像 ValGrind,但在 Windows 上工作。

以下是 3 个可能有帮助的开源替代方案:

  1. DUMA(从外观上看,您必须自己为 Windows 构建它,但 README 包含一些关于这样做的说明)

  2. XMEM

  3. 大象

我不知道它们的性能如何,但它们听起来很有前途,而且看起来它们都以一种或另一种方式在 Windows 上工作。

这个关于管理内存错误的 Microsoft 页面也可能会有所帮助,并且还包含设置内存断点的链接,这可能会帮助您了解您的数据何时首次被删除或更改。祝你好运!

于 2012-05-08T04:05:48.173 回答
2

使用 Microsoft Heap Debugging 的东西,希望你的就是它的设计案例之一。净化将是之后的下一步。

它内置在 Visual Studio 中,在某些情况下很有帮助。如果它有效,它肯定比给 IBM 两三个装满现金的口袋来购买 Purify 更好。

你可以在这里找到信息

TL;DR 在主要的,这样做

int tmpFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
// 打开 (OR) - 将释放的内存块保留在
// 堆的链表并将它们标记为已释放
tmpFlag |= _CRTDBG_DELAY_FREE_MEM_DF;

// 在每次堆操作时开启内存检查
tmpFlag |= _CRTDBG_CHECK_ALWAYS_DF;

// 设置标志的新状态
_CrtSetDbgFlag(tmpFlag);

_CRTDBG_CHECK_ALWAYS_DF如果运行速度太慢,您可以在不同的位置切换标志。但是,我会在检查每个堆操作的情况下运行几次,以便了解问题发生的位置。

于 2012-05-08T08:11:04.937 回答
1

我写了这个博客有一些提示

http://www.atalasoft.com/cs/blogs/loufranco/archive/2007/02/06/6-_2200_Pointers_2200_-on-Debugging-Unmanaged-Code.aspx

您需要做的主要事情是在带有错误的代码仍在堆栈上时发生崩溃或异常。很多时候,在带有错误的代码执行并返回后的某个时间,您会遇到访问冲突,实际上可能是很久以后(计算机时间)。在这种情况下,几乎不可能弄清楚。

在您的情况下,在 delete 中标记了问题,这强烈表明堆已损坏,而 C++ 中的两个常见原因是双重删除和混淆数组删除(当您应该使用 delete[] 或其他方式时使用 delete大约)。

如果你能用简单的代码重现它,我会寻找上面的两个问题。否则,请下载 Microsoft 调试工具并使用gflags +hpa -i program.exe它使堆对损坏更加敏感(它会更快地报告错误)。

于 2012-05-08T12:48:00.033 回答