调试内存损坏(Debugging memory corruption)

2019-07-29 19:46发布

早些时候,我遇到了一个问题,在C动态内存(视觉工作室)。 我有或多或少的工作程序释放中的一个缓冲器时抛出一个运行时错误。 这是一个明确的内存损坏,程序写在缓冲区的末尾。

我的问题是,这是非常耗时的追查。 该错误是在损坏后一路下跌扔了,我不得不手动调试的整个运行发现时的缓冲区结束覆盖。

是否有任何工具\方式协助下这个问题跟踪? 如果该程序就会立即崩溃,我会发现问题快了很多......

这个问题的一个例子:

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

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

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

Answer 1:

我使用的页堆 。 这是微软的工具,它改变了分配是如何工作的。 随着页堆,当你调用malloc,分配被四舍五入到最接近的页面(内存块),并设置为无读虚拟内存的其他页面/不写放置后。 您分配的动态内存对齐,这样你的缓冲区的末尾,仅仅是页面的虚拟页面之前结束之前。 这样,如果你去你的缓冲区的边缘,经常用一个字节,调试器可以很容易地抓住它。



Answer 2:

我用“数据断点”了点。 在你的情况下,当程序崩溃,它可能会首先抱怨是这样的:

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

然后,重新启动您的程序,并设定地址的数据断点0039789C 。 当代码写入该地址时,将停止执行。 它经常发生,我马上找到了这个错误在这一点上。

如果你的程序分配,并多次释放内存,它正好处于这个确切的地址,只是禁用解除分配:

_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_DELAY_FREE_MEM_DF);


Answer 3:

是否有任何工具\方式协助下这个问题跟踪?

是的,这正是其静态代码分析器尝试找到错误的类型。 如splint / PC-Lint

下面是这些工具的列表: http://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis

编辑:在尝试夹板上您的代码段,我得到以下警告:

main.c中:9:2:可能的出界外店:PNUM [I]

据推测,这警告会帮助你。



Answer 4:

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

许多动态跳棋仅捕获访问的对象的外部 ,然后仅当对象是堆中分配。 CheckPointer会发现一个堆分配对象的内部内存访问错误; 它是非法的访问断字段的末尾中的无论字段类型的结构体; 最活跃的棋子不能检测到这样的错误。 它也将找到访问本地人的边缘。



文章来源: Debugging memory corruption