【问题标题】:Debugging memory corruption调试内存损坏
【发布时间】:2012-06-13 15:43:58
【问题描述】:

之前我在 C (visual studio) 中遇到了动态内存问题。 我有一个或多或少的工作程序在释放其中一个缓冲区时引发了运行时错误。这是明显的内存损坏,程序写到了缓冲区的末尾。

我的问题是,追踪起来非常耗时。损坏后错误被抛出,我不得不手动调试整个运行以查找何时覆盖缓冲区结束。

是否有任何工具\方法可以帮助追查此问题?如果程序会立即崩溃,我会更快地发现问题......

问题示例:

int *pNum = malloc(10 * sizeof(int));

//                 ||
//                 \/    
for(int i = 0; i < 13; i++)
{
pNum[i] = 3;
}

// error....
free(pNum);

【问题讨论】:

  • 这不是 'Buffer Secutity Check' 编译器选项 sin VS 所做的吗?
  • 不要使用幻数?
  • @phant0m 这不是真正的代码,它是一个示例,也不是我的代码......缓冲区是根据数据的大小动态分配的,计算它的大小的函数有一个小错误......除了我的问题是关于追踪问题,而不是阻止它......
  • @stijn 它有助于安全性,而不是用于调试...它不会立即崩溃...并且不会显示错误...

标签: c visual-studio-2010 visual-c++ memory-management memory-leaks


【解决方案1】:

是否有任何工具\方法可以帮助追查此问题?

是的,这正是静态代码分析器试图定位的错误类型。例如splint/PC-Lint

以下是此类工具的列表: http://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis

编辑:在您的代码 sn-p 上尝试夹板时,我收到以下警告:

main.c:9:2:可能的越界存储:pnum[i]

大概这个警告会对你有所帮助。

【讨论】:

    【解决方案2】:

    我为此使用“数据断点”。在您的情况下,当程序崩溃时,它可能首先会这样抱怨:

    00397848 处的堆块在 0039789C 处修改,超过请求的 4c 大小

    然后,再次启动程序,并在地址0039789C 处设置数据断点。当代码写入该地址时,执行将停止。我经常会在这一点上立即发现错误。

    如果您的程序重复分配和释放内存,并且恰好位于这个确切地址,只需禁用释放:

    _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_DELAY_FREE_MEM_DF);
    

    【讨论】:

      【解决方案3】:

      我使用pageheap。这是一个来自 Microsoft 的工具,它改变了分配器的工作方式。启用 pageheap 后,当您调用 malloc 时,分配会向上舍入到最近的页面(内存块),并在其后放置一个设置为 no-read/no-write 的附加虚拟内存页面。您分配的动态内存是对齐的,以便缓冲区的末尾正好在虚拟页面之前的页面末尾之前。这样,如果您越过缓冲区的边缘,通常是一个字节,调试器就可以轻松捕获它。

      【讨论】:

        【解决方案4】:

        我们的CheckPointer 工具可以帮助查找内存管理错误。它适用于 GCC 3/4 和 Microsoft 的 C 方言。

        许多动态检查器只捕获对象外部的访问,并且仅当对象是堆分配的。 CheckPointer 将在堆分配对象内部发现内存访问错误;无论字段类型如何,访问结构中字段的末尾都是非法的;大多数动态检查器无法检测到此类错误。它还会在本地人的边缘找到访问权限。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-07-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-10-27
          • 2018-02-27
          • 1970-01-01
          相关资源
          最近更新 更多