[英]Why is my code working when I haven't allocated enough memory using malloc()?
我在SPOJ上正在执行此问题。 http://www.spoj.com/problems/NHAY/ 。 它需要动态地获取输入。 在下面的代码中,即使我没有使用malloc()
将内存分配给char *needle
malloc()
我取l = 1
但是我仍然可以接受任何长度的输入,并且它正在打印出整个字符串。 有时会给出运行时错误。 当我没有为字符串分配足够的内存时,为什么会这样?
#include<stdio.h>
#include<malloc.h>
#include<ctype.h>
#include<stdlib.h>
int main()
{
long long l;
int i;
char *needle;
while(1){
scanf("%lld",&l);
needle =(char *)malloc(sizeof(char)*l);
scanf("%s",needle);
i=0;
while(needle[i]!='\0'){
printf("%c",needle[i]);
i++;
}
free(needle);
}
}
我还在stackoverflow上读到一个字符串是char *
所以我应该声明char *needle
。 如何在代码中使用这个事实? 如果我取l = 1
那么无论输入字符串的长度是多少,字符最多只能包含为char *
指针分配的内存,即1个字节。 我怎样才能做到这一点?
您的代码通过sscanf
将大于分配的空间的字符串复制到malloc
分配的malloc
产生了故意的缓冲区溢出。 之所以“有效”,是因为在大多数情况下,分配的缓冲区位于页面中间的某个位置,因此“仅”将更多数据复制到缓冲区中会覆盖相邻数据。 C(和C ++)对纯C数组不执行任何数组范围检查,因此未捕获错误。
在出现运行时错误的情况下,您很可能会将字符串的一部分复制到未映射和未分配的内存中,这会触发访问冲突。
通常从基础操作系统以固定大小的页面分配内存。 例如,在x86系统上,页面大小通常为4k。 如果您要写入的映射地址距离页面的开头和结尾足够远,则整个字符串将适合页面的边界。 如果您足够接近上限,则代码可能会尝试越过边界进行写操作,从而触发访问冲突。
[关于底层系统的一些假设]
它之所以可以工作,是因为C库管理着操作系统中页面中分配的内存池。 操作系统仅返回页面。 C库返回任意数量的数据。
对于第一次分配,您将获得由操作系统分配并由池管理的读/写页面。 您正在使用库分配的数据的边缘,但位于操作系统返回的页面之内。
做您正在做的事情将破坏池的结构,使用动态内存的更广泛的程序最终将崩溃。
C语言没有默认的绑定检查。 最好情况下,它将在调试时崩溃,有时它将按预期运行。 否则,您将最终覆盖其他存储块。
它并不总是有效。 这是未定义的行为 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.