6

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

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

有什么工具可以帮助追踪这个问题吗?如果该程序就会立即崩溃,我会发现问题快了很多......

问题的例子:

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

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

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

是不是这种什么'缓冲区安全检查'编译器选项罪VS? – stijn

+4

不要使用神奇数字? – phant0m

+5

@ phant0m它不是真正的代码,它是一个例子,也不是我的代码......缓冲区是基于数据大小动态分配的,而计算它大小的函数有一个小错误... 除了我的问题是关于追踪问题,而不是阻止它... –

回答

3

我用pageheap。这是微软改变分配器工作方式的工具。使用pageheap时,当您调用malloc时,分配将四舍五入到最近的页面(一块内存),并在其后面放置一个设置为不可读/不可写的虚拟内存页面。您分配的动态内存已对齐,以便缓冲区的末尾位于虚拟页面之前的页面末尾之前。这样,如果你经过缓冲区的边缘(通常是单个字节),调试器可以很容易地捕获它。

2

是否有任何工具\方式,以协助追查此问题?

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

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

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

的main.c:9: 2:可能的越界商店:pnum [i]

想必这个警告会帮助你。

3

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

堆块在00397848在0039789C过去的修改要求的4C

大小,然后,重新启动您的程序,并设置数据断点在地址0039789C。当代码写入该地址时,执行将停止。经常发生这种情况,我立即发现错误。

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

_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_DELAY_FREE_MEM_DF); 
0

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

许多动态检查程序只捕获一个对象的外部外部,然后只有当该对象是堆分配。 CheckPointer会发现内存访问错误里面的是一个堆分配对象;无论字段类型是什么,访问结构中字段的结尾都是非法的;大多数动态检查器无法检测到这种错误。它还会发现离本地人很近的地方。