Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
gets()如何超过malloc()分配的内存?_C - Fatal编程技术网

gets()如何超过malloc()分配的内存?

gets()如何超过malloc()分配的内存?,c,C,当我将malloc函数用于 为字符指针分配10字节的内存。但是当我赋值的时候 对于该字符指针,如果我尝试分配,它需要超过10个字节。这是怎么可能的 例如: main() { char *ptr; ptr=malloc(10*sizeof(char)); gets("%s",ptr); printf("The String is :%s",ptr); } 样本输出: $./a.out hello world this is for testing 字符串是:he

当我将malloc函数用于 为字符指针分配10字节的内存。但是当我赋值的时候 对于该字符指针,如果我尝试分配,它需要超过10个字节。这是怎么可能的

例如:

main()
{
    char *ptr;
    ptr=malloc(10*sizeof(char));
    gets("%s",ptr);
    printf("The String is :%s",ptr);
}
样本输出:

$./a.out
hello world this is for testing
字符串是:hello world这是用于测试的

现在看看输出,字符数超过10字节。 这怎么可能,我需要清楚的解释。
提前感谢。

这就是为什么使用
get
是件坏事。改用
fgets

malloc
与此无关

. 诚然,理论基础是有用的,是吗?首先,
get()
不允许您指定用于存储字符串的缓冲区的长度。这将允许人们在缓冲区结束后继续输入数据,相信我,这将是个坏消息

: 首先,让我们看看这个函数的原型:

#include <stdio.h>
char *gets(char *s);
我们可以将其传递给
get()
,如下所示:

gets(buf)
到目前为止,一切顺利。或者看起来是这样。。。但实际上,我们的问题已经开始了
gets()
只收到数组(指针)的名称,它不知道数组有多大,,单从指针无法确定。当用户输入文本时,
get()
会将所有可用数据读取到数组中,如果用户明智且输入的字节数少于99字节,则这将是正常的。但是,如果它们输入的值超过99,
get()
将不会停止在数组末尾写入。取而代之的是,它会继续写到它不拥有的内存中

  • 这个问题可能以多种方式表现出来:

  • 没有明显的影响

  • 程序立即终止(崩溃)

  • 在程序生命周期的稍后点终止(可能1秒后,可能15天后)

  • 终止另一个无关的程序

  • 不正确的程序行为和/或计算 ... 这一清单还在继续。这就是“缓冲区溢出”bug的问题,你无法知道它们何时以及如何叮咬你


  • 你只是有一个未定义的行为。()


    使用fgets而不是get

    malloc将保留10个字节(假设char有1个字节),并返回保留区域的起点。
    您执行一个
    获取
    ,因此它获取您键入的文本,并使用指针写入。 Windows/Mac os x/Unix(高级操作系统)具有受保护的内存。 这意味着,当您执行malloc/new操作时,操作系统会为您的程序保留该内存区域。如果另一个程序试图在该区域写入,则会发生分段错误,因为您在不应写入的区域上写入

    您保留了10个字节。
    如果字节11、12、13、14尚未保留给其他程序,则不会崩溃,如果是,则您的程序将访问受保护区域并崩溃。

    malloc
    保留内存供您使用。规则是允许您使用以这种方式和其他方式分配的内存(如定义自动或静态对象),并且不允许您使用未分配给您使用的内存

    但是,
    malloc
    和操作系统并不完全执行这些规则。
    遵守这些规则的义务属于您,而不是
    malloc
    或操作系统

    通用操作系统具有内存保护,可防止一个进程未经允许读取或更改另一个进程的内存。它不会阻止一个进程以不正确的方式读取或更改自己的内存。当您访问不应该访问的字节时,没有任何机制可以始终防止这种情况。内存在那里,您可以访问它,但是您不应该访问它

    get
    是一个设计糟糕的例程,因为如果输入行足够长,它将写入任意数量的内存。这意味着您无法阻止它写入超过您分配的内存。您应该改用
    fgets
    。它有一个参数限制它可以写入的内存量

    通用操作系统以称为页的块分配内存。页面的大小可能是4096字节。当
    malloc
    为您分配内存时,它可以从操作系统获得的最小大小是一页。当您请求10个字节时,
    malloc
    将获得一个页面,如果需要,在其中选择10个字节,记录页面的一小部分已分配,但其余部分可供其他使用,并将指向该10个字节的指针返回给您。当您进行进一步分配时,
    malloc
    可能会从同一页分配额外的字节

    当您超出分配给您的字节数时,您违反了规则。如果进程的其他部分没有使用这些字节,那么您可能不会受到这种违规行为的影响。但您可能会更改malloc用来跟踪分配的数据,您可能会更改作为单独内存分配一部分的数据,或者,如果您做得足够深入,您可能会完全更改单独页面中的数据,并且这些数据正由程序的完全不同部分使用


    通用操作系统确实提供了一些保护,防止进程中内存的不当使用。如果尝试访问虚拟地址空间中未映射的页面,或者尝试修改标记为只读的页面,则会触发错误,并且进程将中断。但是,此保护仅适用于页面级别,不会防止您错误地使用分配给进程的内存。

    OP:。。。字符数超过10个字节。
    gets(buf)