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

时间:2013-11-20 11:24:07

标签: c

我对malloc和realloc函数有疑问,当我使用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

String是:hello world这是用于测试

现在看输出字符数超过10个字节。 怎么可能,我需要明确的解释。 在此先感谢。

5 个答案:

答案 0 :(得分:6)

这就是为什么使用gets邪恶的东西。请改用fgets

malloc与此无关

Don't use gets()

  

不可否认,理由是有用的,是吗?首先, gets()不允许您指定存储字符串的缓冲区长度。这样可以让人们在缓冲区末尾输入数据,并且相信我,这将是坏消息。

Detailed explanation

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

#include <stdio.h>
char *gets(char *s);

您可以看到唯一的参数是char指针。那么,如果我们制作一个这样的数组:

char buf[100];

我们可以将其传递给gets(),如此:

gets(buf)

到目前为止,这么好。或者似乎......但实际上我们的问题已经开始了。 gets()只接收到数组的名称(指针),它不知道数组有多大,并且不可能仅通过指针来确定。当用户输入文本时,gets()会将所有可用数据读入数组,如果用户理智且输入少于99个字节,这将没有问题。但是,如果输入超过99,gets() 将不会停止在数组末尾写入。相反,它继续写到结束并进入它不拥有的内存。

  1. 此问题可能以多种方式表现出来:

  2. 没有可见的影响

  3. 立即终止程序(崩溃)

  4. 在节目生命时间的晚些时候终止(可能是1秒后,可能是15天后)

  5. 终止另一个无关的计划

  6. 程序行为和/或计算不正确 ... 而这样的例子不胜枚举。这是“缓冲区溢出”错误的问题,你无法分辨它们何时以及如何咬你。

答案 1 :(得分:2)

你刚才有一个未定义的行为。 (More information here

使用fgets而不是获取!

答案 2 :(得分:2)

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

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

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

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

通用操作系统以称为页面的块分配内存。页面大小可能是4096字节。当malloc为您分配内存时,它可以从操作系统获得的最小大小是一页。当你要求十个字节时,malloc将得到一个页面,如果有必要,在其中选择十个字节,保留记录表明页面的一小部分已被分配,但其余部分可用于其他用途,并返回指向你的十个字节的指针。当您进行进一步分配时,malloc可能会从同一页面分配额外的字节。

当您超出已分配给您的字节时,您违反了规则。如果您的进程的其他任何部分没有使用这些字节,您可能会逃避此违规。但是您可能会更改malloc用于跟踪分配的数据,您可能会更改作为单独内存分配的一部分的数据,或者如果您走得足够远,可能会更改单独分配的数据页面完全正在由程序的完全不同部分使用。

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

答案 3 :(得分:0)

malloc将保留10个字节(在您的情况下假设char有1个字节)并将返回保留区域的起始点。
你做一个gets,所以它得到你输入的文字并用你的指针写。 Windows / Mac OS x / Unix(Advances OS'S)具有受保护的内存。 这意味着,当您执行malloc / new时,操作系统会为您的程序保留该内存区域。如果另一个程序试图在该区域中写入,则会发生分段错误,因为您在不应该写入的区域上进行了写入。

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

答案 4 :(得分:0)

OP:...字符数超过10个字节。这怎么可能?
答:由gets()完成写入外部分配的内存是未定义的行为 - UB。 UB的范围从你想要的崩溃和燃烧开始。

真正的问题并非令人遗憾地使用gets(),而是认为C语言应该防止内存访问误用。 C不会阻止它。代码应该阻止它。 C不是一种具有大量幕后保护的语言。如果写入ptr[10]不好,请不要这样做。不要调用可能执行此操作的函数,例如gets()。像生活的许多方面一样 - 练习安全计算。

C为你提供了很多绳子来做各种各样的事情,包括足够的绳索让你自己上吊。