C 在Linux中,有没有一种方法可以知道传递给_free_钩子的指针的大小?
我想跟踪一个大型应用程序当前分配了多少内存 我发现我可以在malloc/free/realloc周围安装钩子,以便拦截内存分配调用: 所以我要跟踪的是分配的总字节数-释放的总字节数 现在的问题是free只接受一个指针,而不接受一个大小 在中,我可以在mallochook中创建我自己的映射或hashmap,跟踪为该指针分配了多少内存,但这会导致相当大的开销C 在Linux中,有没有一种方法可以知道传递给_free_钩子的指针的大小?,c,linux,malloc,hook,free,C,Linux,Malloc,Hook,Free,我想跟踪一个大型应用程序当前分配了多少内存 我发现我可以在malloc/free/realloc周围安装钩子,以便拦截内存分配调用: 所以我要跟踪的是分配的总字节数-释放的总字节数 现在的问题是free只接受一个指针,而不接受一个大小 在中,我可以在mallochook中创建我自己的映射或hashmap,跟踪为该指针分配了多少内存,但这会导致相当大的开销 当调用free时(使用默认的g++malloc),有没有办法(即使有点麻烦)在Linux(64位)上获得ptr的大小 malloc_usab
当调用free时(使用默认的g++malloc),有没有办法(即使有点麻烦)在Linux(64位)上获得ptr的大小 malloc_usable_size()返回文件中可用的字节数 动态分配的缓冲区ptr,可能大于 请求的大小(但如果 请求成功)。通常,您应该存储 请求的分配大小,而不是使用此函数
这不是对您的问题的直接回答,但鉴于您对分配的总内存感兴趣,以下是解决方案:
uordblks
字段
请注意,这不是一个标准的POSIX函数,但我想这正是您对像这样的非标准自省的期望…您需要在malloc中安装一个钩子来构建一个指针表,缓存请求块的大小,然后当您空闲时,在以前的malloc项目数据库中搜索指针
这样,您将知道当前分配的堆总和要减少多少(如果这是您的目标),并且将有一个方便的位置列出仍保留在内存中的堆的所有“区域”。内存块的大小通常存储在指针的正下方。虽然这是一个黑客攻击(你说我可以…),但以下代码在我的Linux机器上运行:
#include <stdio.h>
#include <stdlib.h>
int main(){
int *p, n=123;
p = (int*)malloc(n*sizeof(int));
printf("allocated %d bytes for p\n", n*sizeof(int));
printf("p[-2] : %d \n", *(p-2));
printf("malloc_useable_size(p) : %d\n", malloc_usable_size(p));
free(p);
}
请注意,p[-2]中的大小并不完全是492
-由于内务管理和边界对齐等原因,会占用一些额外的空间
另请注意-这与gcc
编译器一起工作;但是g++
抱怨指针转换,并且我没有声明malloc\u useable\u size()
。在看到@fanl的答案后,出于好奇,我添加了这一行。在看到@OliCharlesworth的答案后,我还玩了一下mallinfo的输出
您可以更改n的值,您将看到事情非常一致-例如,如果您将n(在我上面的代码中)从100步移到119步,则不同感兴趣变量的值如下所示:
n | p[-2] | usable | uordblks
----+-------+--------+---------
100 417 408 416
101 417 408 416
102 417 408 416
103 433 424 432
104 433 424 432
105 433 424 432
106 433 424 432
107 449 440 448
108 449 440 448
109 449 440 448
110 449 440 448
111 465 456 464
112 465 456 464
113 465 456 464
114 465 456 464
115 481 472 480
116 481 472 480
117 481 472 480
118 481 472 480
119 497 488 496
可用的
和p[-2]
之间总是有9的差异,而p[-2]
和uordblks之间总是有1的差异。p[-2]
方法的优点在于,它可以准确地告诉您要什么--这个指针的大小。其他的电话可能会告诉你你真正想要什么
PS对于非常大的内存块,很可能需要查看位于*((long int*)(p)-1)
的长整数。这给了我一个很棒的宏的灵感:
#define PSIZE(a) (*((long int*)(a)-1))
然后,您可以使用
printf("my pointer size is %ld\n", PSIZE(myPointer));
不必担心指针的类型。我确认这适用于不同类型的指针以及大于4G的块。显然,您可以决定在宏中减去1,使数字与mallinfo()完全一致
编辑:对指针下方存储的内容的更完整描述,请参见以下答案之一。这表明我观察到的“+1”实际上是由于LSB中存储的标志。正确的方法是用~3和结果,清除两个LSB,然后从结果中减去(长整型*)的大小(实际上原始答案减去2*sizeof(无符号长整型),但我认为这是错误的):
链接的答案强烈建议仅在调试时使用此选项,而不要在实际代码中依赖它。我觉得有必要重复这一警告。这在很大程度上取决于glibc的malloc du jour如何做事。。。最好用@fanl的答案。问题的可能重复部分相似,但不完全相同。那个人打算用它来计算一个数组在代码中的长度,在这些答案中建议避免使用这个数组。在这种情况下,这个问题只是为了跟踪总记忆。也许-但在这两种情况下被接受的答案是相同的。。。“使用malloc\u可用的大小()。这至少让它在我心目中成为“可能的复制品”。通过创建链接,我们为偶然发现一个问题的人提供了看到更多可能答案的机会。
printf("my pointer size is %ld\n", PSIZE(myPointer));
#define PSIZE(a) ((*((long int*)(a)-1))&~3 - sizeof(long int*))