如果我打电话:
char *myChar = (char *)malloc(sizeof(char));
我可能会使用超过1个字节的内存,因为malloc可能会自己使用一些内存来跟踪堆中的空闲块,并且通过始终对齐分配可能会有效地花费我一些内存沿着某些边界。
我的问题是:有没有办法找出特定malloc
调用实际消耗了多少内存,包括有效的对齐成本以及使用的开销malloc
/ free
?
为了清楚起见,我不要求查看调用malloc
后指针指向的内存量。相反,我正在调试一个使用大量内存的程序,我想知道代码的哪些部分正在分配多少内存。我希望能够使内部记忆会计与top报告的数字非常接近。理想情况下,我希望能够在每个malloc
调用的基础上以编程方式执行此操作,而不是在检查点获取摘要。
答案 0 :(得分:8)
没有可移植的解决方案,但是对于您感兴趣的环境,可能存在特定于操作系统的解决方案。
例如,在Linux上使用glibc
,您可以使用mallinfo()
中的<malloc.h>
函数返回struct mallinfo
。此结构的uordblks
和hblkhd
成员包含程序使用的动态分配的地址空间,包括簿记开销 - 如果您在每次malloc()
调用之前和之后取得此差异,您将知道该呼叫使用的空间量。 (每次调用malloc()
时,开销不一定是恒定的。)
使用您的示例:
char *myChar;
size_t s = sizeof(char);
struct mallinfo before, after;
int mused;
before = mallinfo();
myChar = malloc(s);
after = mallinfo();
mused = (after.uordblks - before.uordblks) + (after.hblkhd - before.hblkhd);
printf("Requested size %zu, used space %d, overhead %zu\n", s, mused, mused - s);
实际上,除非您进行非常大量的非常小的分配,否则开销很可能很小,无论如何这都是个坏主意。
答案 1 :(得分:2)
这实际上取决于实施。你应该真的使用一些内存调试器。在Linux上Valgrind的Massif工具非常有用。有像dmalloc这样的内存调试库......
那就是典型的开销:
free()
'd块中使用,被重用于已分配块中的应用程序存储。double
。因此,最小大小可以是16到24个字节。最小开销可以是4个字节。
但是你也可以通过映射内存页面(通常是4Kb)来满足每个分配,这意味着较小分配的开销将是巨大的。我认为OpenBSD就是这样做的。
答案 2 :(得分:0)
C库中没有定义任何内容来查询malloc()
调用所使用的物理内存总量。分配的内存量由malloc()
调用的幕后连接的内存管理器控制。除了操作系统本身需要的额外内存之外,内存管理器可以为其内部跟踪目的分配尽可能多的额外内存。当你调用free()
时,它会访问内存管理器,内存管理器知道如何访问额外的内存,以便正确释放所有内存,但是你无法知道涉及多少内存。如果你需要那么多细节,那么你需要编写自己的内存管理器。
答案 3 :(得分:0)
如果您使用valgrind / Massif,则可以选择显示malloc
值或top
值,这与我的经验有很大不同。以下是Valgrind手册http://valgrind.org/docs/manual/ms-manual.html的摘录:
...但是,如果您想测量程序使用的所有内存, 你可以使用--pages-as-heap = yes。启用此选项时 Massif的正常堆块分析由较低级别的页面替换 剖析。通过mmap和类似系统调用分配的每个页面都是 被视为一个独特的块。这意味着代码,数据和BSS 所有段都是测量的,因为它们只是内存页面。即便是 堆栈被测量......