Malloc – >分配了多少内存?
# include # include # include # include int main () { char * buffer; buffer = malloc (2); if (buffer == NULL){ printf("big errors"); } strcpy(buffer, "hello"); printf("buffer is %s\n", buffer); free(buffer); return 0; }
我为指针/ char buffer
分配了2个字节的内存,但是如果我为它分配C风格的字符串hello
,它仍会打印整个字符串,而不会给我任何错误。 为什么编译器没有给我一个错误,告诉我没有足够的内存分配? 我读了几个问题,询问如何检查malloc
实际分配的内存量,但我没有找到具体的答案。 free
函数不应该确切地知道buffer
分配了多少内存吗?
编译器不知道。 这是C. malloc
属于运行时的喜悦和恐怖。 所有的编译器都知道你告诉它它返回一个void *,它不知道要复制多少,或者strcpy
要复制多少。
像valgrind这样的工具可以检测到其中的一些错误。 其他编程语言让你更难以自己拍脚。 不是C.
生产malloc()
实现不应该阻止您尝试写入您分配的内容。 假设如果分配123个字节,则将使用全部或小于分配的值。 malloc()
,为了提高效率,必须假设程序员要跟踪他们的指针。
使用未明确且成功请求malloc()
是未定义的行为。 由于malloc()
实现针对字节对齐进行了优化,因此您可能要求n个字节但得到n + x 。 或者你可能正在写一个黑洞。 你永远不可能知道,这就是为什么它是未定义的行为。
话虽如此 …
有malloc()
实现为您提供内置的统计和调试 ,但是这些实现需要代替标准的malloc()
工具,就像您使用垃圾收集品种一样 。
我还看到了严格为LD_PRELOAD设计的变体,它们公开了一个函数,允许你定义一个至少有一个void指针作为参数的回调。 该参数期望包含统计数据的结构。 电栅栏等其他工具只会根据导致溢出或访问无效块的确切指令暂停程序。 正如@R ..在评论中指出的那样,这对于调试很有用,但效率非常低。
诚然或者(正如他们所说)“在一天结束时” – 在这种情况下使用诸如Valgrind及其相关工具( massif )之类的堆分析器会更容易,这将为您提供相当多的信息。 在这种特殊情况下,Valgrind会指出明显的 – 你写过了分配的边界。 在大多数情况下,当这不是故意的时候 ,一个好的分析器/错误检测器是无价的。
由于以下原因,并不总是可以使用分析器:
- 在分析器下运行时的时序问题(但是在任何时候对
malloc()
调用都是截获的)。 - Profiler不适用于您的平台/ arch
- 调试数据(来自日志记录
malloc()
)必须是程序的组成部分
我们使用了我在HelenOS中链接的库的变体(我不确定他们是否还在使用它)已经有一段时间了,因为已知VMM的调试会引起精神错乱。
考虑到替代品的下降,考虑未来的后果,当考虑到malloc()
设施时,你几乎总是想要使用系统发布的东西。
malloc内部分配的数量取决于实现和OS依赖(例如,8字节或更多的倍数)。 即使编译器和运行时没有检测到错误,写入未分配的字节也可能导致覆盖其他变量的值。 自由函数记住与分配的区域分开的字节数,例如在空闲列表中。
为什么编译器没有给我一个错误告诉我没有足够的内存分配?
C
不会阻止你使用你不应该使用的内存。 您可以使用该内存,但它很糟糕并导致未定义的行为。 你在一个你不应该写的地方写作。 此程序可能看起来运行正常,但可能会在以后崩溃。 这是UB
。 你不知道会发生什么。
这是你的strcpy()
发生的事情。 你写的不是你自己的,但语言不能保护你。 所以你应该确保你总是知道你在写什么和在哪里,或者确保你在超出有效的记忆界限时停下来。
我读了几个问题,询问如何检查malloc实际分配的内存量,但我没有找到具体的答案。 “免费”function不应该知道有多少内存准确分配给“缓冲区”吗?
malloc()
可能会分配比您请求位填充更多的内存。
更多: http : //en.wikipedia.org/wiki/Data_structure_alignment
free()
free-s与malloc()
分配的数量完全相同,但它并不像你想象的那么聪明。 例如:
int main() { char * ptr = malloc(10); if(ptr) { ++ptr; // Now on ptr+1 free(ptr); // Undefined Behaviour } }
你应该总是free()
一个指向第一个块的指针。 free(0)
是安全的。
您已经写过您分配的缓冲区的末尾。 结果是未定义的行为。 一些具有正确选项的运行时库至少具有一些诊断此类问题的能力,但并非所有问题,甚至是那些仅在运行时执行此操作的问题,并且通常仅在使用正确的选项进行编译时。
Malloc – >分配了多少内存?
使用malloc分配内存时。 成功时,它分配内存,默认分配为128k。 第一次调用malloc给你128k。
你要求的是buffer = malloc (2);
虽然你要求2个字节。 它已经分配了128k。
strcpy(buffer, "hello");
分配了128k块,它开始处理您的请求。 “Hello”字符串可以适合这个。
这个pgm会让你清楚。
int main() { int *p= (int *) malloc(2);---> request is only 2bytes p[0]=100; p[1]=200; p[2]=300; p[3]=400; p[4]=500; int i=0;
for(; i <5; i ++,p ++) enter code here
printf(“%d \ t”,* p);
}
在第一次调用malloc时。 它从处理您的请求(2个字节)中分配128k —>。 字符串“hello”可以放入其中。 再次调用malloc时,它会处理128k的请求。
超过128k它使用mmap接口。 您可以参考malloc的手册页。
没有编译器/平台独立的方法来找出实际分配了多少内存malloc。 一般来说,malloc的分配比你要求的稍多一点:
http://41j.com/blog/2011/09/finding-out-how-much-memory-was-allocated/
在Linux上,您可以使用malloc_usable_size来查找可以使用的内存量。 在MacOS和其他BSD平台上,您可以使用malloc_size。 上面链接的post有这两种技术的完整例子。