繁体   English   中英

当我没有使用malloc()分配足够的内存时,为什么我的代码可以工作?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM