我如何获得使用malloc()分配的内存块的大小?

可能重复:
我怎样才能从C中的指针获取数组的大小?
有没有什么办法来以编程方式确定一个C ++数组的大小? 如果没有,为什么?

我从C风格函数中得到一个分配内存块的指针。 现在,对于debugging目的来说,知道这个指针指向的分配的内存块有多大是非常有趣的。

有没有什么比盲目超越边界挑衅exception更优雅?

在此先感谢,安德烈亚斯

编辑:

我在Windows上使用VC ++ 2005,在Linux上使用GCC 4.3

EDIT2:

我在VC + + 2005下_msize不幸的是,它在debugging模式下导致一个exception….

EDIT3:

好。 我已经尝试过上面描述的例外情况,并且它工作正常。 至less在我debugging的时候,确保在调用库之后立即退出缓冲区边界。 奇迹般有效。

它只是不够优雅,并不适用于生产代码。

这不是标准的,但如果你的图书馆有一个msize()函数,会给你的大小。

一个常见的解决scheme是用自己的函数包装malloc,logging每个请求以及大小和结果的内存范围,在发布版本中可以切换回“真正的”malloc。

如果您为了debugging而不介意低级暴力,您可以#定义macros以将调用挂接到malloc并释放,并将大小的前4个字节填充。

为了调子

 void *malloc_hook(size_t size) { size += sizeof (size_t); void *ptr = malloc(size); *(size_t *) ptr = size; return ((size_t *) ptr) + 1; } void free_hook (void *ptr) { ptr = (void *) (((size_t *) ptr) - 1); free(ptr); } size_t report_size(ptr) { return * (((size_t *) ptr) - 1); } 

然后

 #define malloc(x) malloc_hook(x) 

等等

C运行时库不提供这样的function。 而且,故意挑起一个例外也不会告诉你这个区块有多大。

通常在C中解决这个问题的方法是维护一个单独的variables来跟踪分配块的大小。 当然,这有时是不方便的,但通常没有其他方法可以知道。

您的C运行时库可能会提供一些堆debuggingfunction,可以查询分配的块(毕竟, free()需要知道块有多大),但是这样的事情将是不可移植的。

不,并且在超出边界时不能依靠exception,除非它在您的实现文档中。 这是你不需要知道编写程序的东西的一部分。 如果你真的想知道的话,深入你的编译器的文档或源代码。

没有标准的C函数来做到这一点。 根据你的平台,可能有一个不可移植的方法 – 你使用的是什么OS和C库?

请注意,引发exception是不可靠的 – 在你拥有的块之后可能会有其他分配,所以在超过当前块的限制之前,你可能不会得到exception。

像Valgrind的memcheck和Google的TCMalloc (堆检查器部分)之类的内存检查器会跟踪这类事情。

您可以使用TCMalloc来转储一个堆configuration文件,该configuration文件显示事物的分配位置,或者您可以检查一下,以确保您的堆在使用SameHeap()的程序执行中的两个点是相同的。

有了gccGNU linker ,你可以轻松地包装malloc

 #include <stdlib.h> #include <stdio.h> void* __real_malloc(size_t sz); void* __wrap_malloc(size_t sz) { void *ptr; ptr = __real_malloc(sz); fprintf(stderr, "malloc of size %d yields pointer %p\n", sz, ptr); /* if you wish to save the pointer and the size to a data structure, then remember to add wrap code for calloc, realloc and free */ return ptr; } int main() { char *x; x = malloc(103); return 0; } 

和编译

 gcc ac -oa -Wall -Werror -Wl,--wrap=malloc 

(当然,这也适用于使用g ++编译的c ++代码,如果你愿意,也可以使用new运算符(通过它的名字)。

实际上,静态/dynamic加载的库也将使用您的__wrap_malloc

部分解决scheme:在Windows上,您可以使用PageHeap在分配的块之外捕获内存访问。

PageHeap是Windows内核中的一个替代内存pipe理器(在NT版本中,但现在没有人应该使用任何其他版本)。 它需要在一个进程中进行每一个分配,并返回一个内存块,其末尾与内存页面的末尾alignment,然后使得下一个页面无法访问(不能读取,不能写入)。 如果程序试图读取或写入块的末尾,您将遇到访问冲突,您可以使用您最喜欢的debugging器。

如何获取它:从Microsoft下载并安装用于Windows的debugging工具: http : //www.microsoft.com/whdc/devtools/debugging/default.mspx

然后启动GFlags实用程序,转到第三个选项卡并input可执行文件的名称,然后点击该键。 检查PageHeapcheckbox,单击确定,你很好去。

最后一件事情是:当你完成debugging时,不要忘记再次启动GFlags,并禁用PageHeap。 GFlags将此设置input到registry中(在HKLM \ Software \ Microsoft \ Windows NT \ CurrentVersion \ Image File Execution Options \下),因此即使在重新启动时也是持久的。

另外,请注意,使用PageHeap可以极大地增加应用程序的内存需求。

做你想做的是做分配器。 如果过滤所有的请求,然后logging它们以进行debugging,那么当内存被释放时你可以find你想要的。

另外,你可以在程序结束时检查是否所有分配的块被释放,如果没有,列出它们。 这样一个雄心勃勃的图书馆甚至可以通过macros来获取FUNCTIONLINE参数,让你知道你在哪里泄漏内存。

最后,Microsoft的MSVCRT提供了一个可debugging的堆,它有许多有用的工具,您可以在debugging版中使用它来查找内存问题: http : //msdn.microsoft.com/zh-cn/library/bebs9zyz.aspx

在Linux上,您可以使用valgrind来查找许多错误。 http://valgrind.org/