# include <stdio.h>
# include <stdbool.h>
# include <string.h>
# include <stdlib.h>
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
分配了多少内存吗?
答案 0 :(得分:14)
编译器不知道。这是C. malloc
属于运行时的喜悦和恐惧。所有的编译器都知道你告诉它它返回一个void *,它不知道要复制多少,或者strcpy
要复制多少。
像valgrind这样的工具可以检测到其中的一些错误。其他编程语言让你更难以自己拍摄。不是C.
答案 1 :(得分:4)
没有生产malloc()
实施可以阻止您尝试写过您分配的内容。假设如果分配123个字节,则将使用全部或小于分配的值。 malloc()
,为了提高效率,必须假设程序员要跟踪他们的指针。
使用未明确并且成功要求malloc()
给您的内存是未定义的行为。由于malloc()
实现优化了字节对齐,您可能已经要求 n 字节但得到 n + x 。或者你可能正在写一个黑洞。你永远不会知道,这就是为什么它是未定义的行为。
有人说......
有malloc()
个实现可以让您内置statistics and debugging,但是需要使用这些实现来代替标准malloc()
工具,就像使用{{{}}时一样3}}。
我还看到了严格为LD_PRELOAD设计的变体,它们公开了一个函数,允许你定义一个至少有一个void指针作为参数的回调。该参数期望包含统计数据的结构。像garbage collected variety这样的其他工具只会根据导致溢出或访问无效块的确切指令暂停程序。正如@R ..在评论中指出的那样,这对调试很有帮助,但效率非常低。
诚实地或(正如他们所说)'在一天结束时' - 在这种情况下使用诸如electric fence之类的堆分析器及其相关工具(Valgrind)要容易得多这将为您提供相当多的信息。在这种特殊情况下,Valgrind会指出明显的 - 你写过了分配的边界。在大多数情况下,当这不是故意时,一个好的分析器/错误检测器是无价的。
由于以下原因,并不总是可以使用分析器:
malloc()
的任何一次调用被截获时都很常见。)malloc()
)必须是程序我们使用了我在HelenOS中链接的库的变体(我不确定他们是否还在使用它)已经有一段时间了,因为已知VMM的调试会导致精神错乱。
但是,考虑到替换的减少时,请仔细考虑未来的后果,当谈到malloc()
设施时,您几乎总是想要使用系统发布的内容。
答案 2 :(得分:1)
malloc内部分配的内容依赖于实现和OS依赖(例如,8字节或更多的倍数)。即使编译器和运行时没有检测到错误,写入未分配的字节也可能导致覆盖其他变量的值。自由函数会记住与分配区域分开的字节数,例如在空闲列表中。
答案 3 :(得分:1)
为什么编译器没有给我一个 错误告诉我没有足够的 内存分配?
C
不会阻止你使用你不应该使用的内存。您可以使用该内存,但它很糟糕并导致未定义的行为。你在一个你不应该写的地方写作。此程序可能看起来运行正常,但可能会在以后崩溃。这是UB
。你不知道会发生什么。
这是您strcpy()
发生的事情。你写的不是你自己的,但语言不能保护你。所以你应该确保你总是知道你在写什么和在哪里,或者当你要超过有效的记忆范围时确保你停止。
我读了几个问的问题 如何查看malloc的内存量 实际分配,但我没有找到 具体答案。不应该'免费' 功能必须知道多少内存 是否完全分配给'缓冲区'?
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)
是安全的。
答案 4 :(得分:1)
您已经写过您分配的缓冲区的末尾。结果是未定义的行为。一些具有正确选项的运行时库至少具有一些诊断此类问题的能力,但不是所有问题,甚至是那些只在运行时执行此操作的问题,通常只有在使用正确的选项进行编译时才会这样做。
答案 5 :(得分:0)
Malloc - &gt;已经分配了多少内存?
使用malloc分配内存时。成功时,它分配内存,默认分配为128k。第一次调用malloc会给你128k。
您请求的是buffer = malloc (2);
虽然您请求了2个字节。它已经分配了128k。
strcpy(buffer, "hello");
分配了128k块,开始处理您的请求。 “你好”
字符串可以适合这个。
这个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;
有(;我小于5;我++,的p ++)enter code here
的printf( “%d \ t” 的,* P);
}
首次调用malloc。它分配128k ---&gt;从它处理您的请求(2个字节)。字符串“hello”可以放入其中。再次调用malloc时,它会处理128k的请求。
超过128k它使用mmap接口。您可以参考malloc的手册页。
答案 6 :(得分:0)
没有编译器/平台独立的方法来查明实际分配了多少内存malloc。一般来说,malloc的分配比你要求它看得多一点:
http://41j.com/blog/2011/09/finding-out-how-much-memory-was-allocated/
在Linux上,您可以使用malloc_usable_size来查找可以使用的内存量。在MacOS和其他BSD平台上,您可以使用malloc_size。上面链接的帖子提供了这两种技术的完整示例。