我是C的新手。对不起,如果已经回答了这个问题,我找不到答案,所以我们走了......
我正在尝试理解malloc()在C中是如何工作的。我有这段代码:
#define MAXLINE 100
void readInput(char **s)
{
char temp[MAXLINE];
printf("Please enter a string: ");
scanf("%s", temp);
*s = (char *)malloc((strlen(temp)+1)*sizeof(char)); // works as expected
//*s = (char *)malloc(2*sizeof(char)); // also works even when entering 10 chars, why?
strcpy ((char *)*s, temp);
}
int main()
{
char *str;
readInput(&str);
printf("Your string is %s\n", str);
free(str);
return 0;
}
问题是为什么当我像这样调用malloc()时,程序不会崩溃(或者至少剥离剩余的字符):
*s = (char *)malloc(2*sizeof(char)); // also works even when entering 10 chars, why?
如果我输入一个超过两个字符的字符串,这不会导致缓冲区溢出吗?我理解malloc(),它为数据分配一个固定的空间,所以肯定只为两个字符分配空间将允许字符串最多一个可用字符('0'是第二个),但它仍然是打印输入所有10个字符。
P.S。如果有任何不同,我正在使用Xcode。
谢谢, 西蒙
答案 0 :(得分:2)
这很好,因为你很幸运!通常,操作系统会为程序提供略大于2个字节的块。
如果操作系统在您要求2个字节时实际给出了16个字节,则可以写入16个字节,而操作系统不会注意到它。但是,如果您的程序中有另一个malloc()
使用了其他14个字节,那么您可以将这些变量内容写下来。
操作系统并不关心你在自己的程序中乱搞。如果您在操作系统提供的内容外写作,您的程序将只会崩溃。
尝试写入200个字节并查看它是否崩溃。
编辑:
malloc()
和free()
使用一些堆空间来维护有关已分配内存的信息。该信息通常存储在存储块之间。如果溢出缓冲区,则可能会覆盖此信息。
答案 1 :(得分:2)
是将更多数据写入分配的缓冲区是缓冲区溢出。但是,在C中没有缓冲区溢出检查,并且在缓冲区之后是否存在有效内存,而不是代码看起来可以正常工作。
但是你所做的就是写入你不拥有的内存并且可能已经破坏了堆。您对free
或malloc
的下一次通话可能会崩溃,或者如果没有下一次通话,以后的某个通话可能会崩溃,或者您可能会很幸运,malloc
向您提供的缓冲区比您大请求,在这种情况下,你永远不会看到问题。
答案 2 :(得分:2)
如果我输入一个包含两个以上字符的字符串,这不会导致缓冲区溢出吗?
绝对。但是,C在运行时没有检查边界;它假设您在分配内存时知道自己在做什么,并且知道可用的内容。如果你超过缓冲区的末尾,你将破坏之前的任何东西。
是否导致代码崩溃取决于之前的内容以及您使用的内容。并非所有溢出都会导致程序崩溃,并且堆中的溢出可能不会导致任何(明显的)问题。
答案 3 :(得分:1)
这是因为即使你没有分配内存,内存也存在。 您正在访问不属于您的数据,可能使用良好的调试器或静态分析器,您会看到错误。
此外,如果您的变量位于您分配的块后面,则可能会被您输入的内容覆盖。
答案 4 :(得分:1)
这只是未定义行为的案例之一。你不幸的是你得到了预期的结果。
答案 5 :(得分:1)
确实会导致缓冲区溢出。但是C没有做任何事情来防止缓冲区溢出。大多数malloc的实现都没有。
通常,缓冲区溢出崩溃只发生在......
(......但这些事情取决于所涉系统的具体情况。)
如果幸运的话,完全有可能缓冲区溢出永远不会导致崩溃。虽然它可能会产生其他不太明显的问题。
答案 6 :(得分:1)
malloc()是在Stdlib.h头文件中指定的函数调用。如果您使用数组,则必须在使用数据之前修复内存长度。但是在malloc()函数中,您可以在需要时以所需大小分配内存。当您通过malloc()分配内存时,它将搜索内存模块并找到空闲块。即使内存块位于不同的位置,它也会分配一个地址并连接所有块。 当你的过程完成后,你可以释放它。自由意味着,分配内存仅在RAM中。处理完该函数并生成一些数据后,您将把数据转移到硬盘或任何其他永久存储器。之后,您可以释放该块,以便您可以使用其他数据。 如果你要通过指针函数,使用malloc()就不能生成数据块。 New()是c ++的关键字。
当你不知道编程时你需要多大的内存空间时,你可以使用函数malloc
void * malloc(size_t size); malloc()函数应为一个对象分配未使用的空间,该对象的大小以字节为单位由size指定,其值未指定。
它的工作原理是什么......
所以 你的系统有自由链列表,它列出了所有可用的内存空间,malloc搜索这个列表,直到找到一个足够大的空间,你需要它。然后它在2中打破这个空间,向你发送你需要的空间并将另一个放回到列表中。它打破了2 ^ n的大小,你的列表中没有奇怪的空间大小,这就像Lego一样简单。
当你打电话'免费'时你的区块会回到免费链列表。