[gets()和C中的缓冲区

问题描述 投票:-1回答:4

我知道,使用gets()是一个非常糟糕的主意,因为它可能导致缓冲区溢出。但是我有一些疑问。

假设一个c程序具有以下代码-

    char word[6];
    gets(word);
    puts(word);

例如,如果我输入-HELLO WORLD,是否假设gets()将其读取为[H] [E] [L] [L] [O] [ ],其余的进入输入缓冲区是否正确?

如果发生这种情况,puts()如何获取数据以显示完整的字符串?

c string gets
4个回答
3
投票

假设gets()将其读取为[H] [E] [L] [L] [O] [],其余都进入输入缓冲区是正确的吗?

没有尝试过度填充缓冲区word[]undefined behavior。可能发生任何事情。其余代码无关紧要。发生这种情况时,未对缓冲区的内容进行任何指定。


2
投票

否,假设它在空间用尽时才停止就不正确;它不知道有多少可用空间。 gets只是继续读取字符并写入相邻的内存,从而调用未定义的行为。您可能会很幸运,并且没有使用相邻的内存(在gets之前或之后),并且puts“正常工作”。否则它可能会覆盖您的堆栈指针,并且一切都会爆炸。或者,它可能会正确写入缓冲区,但是在puts到达之前,缓冲区的位会被覆盖。还是其他这是未定义的行为。

不要这样做。请勿使用gets


2
投票

gets功能一次读取一行。因此,在您的示例中,它将尝试将11个字符的“ HELLO WORLD”读入只有6个字符宽的缓冲区中。这会使缓冲区溢出,导致undefined behavior

由于gets无法限制它可以读取多少个字符,因此很危险,这就是为什么将其从C11标准中删除的原因。


1
投票

您的问题建议您认为gets可能以某种方式知道word只有6个字符长,因此它仅用6个字符填充,其余部分留在与输入流关联的缓冲区中。事实并非如此。呼叫gets(word)将[[0]的起始地址only传递给word。这就是它收到的所有内容—起始位置。它不接收任何有关长度的信息。 gets从输入流中读取,直到读取换行符或遇到文件结尾或发生错误为止。

如果您输入“ HELLO WORLD”,并且程序打印出来,那是因为gets读取了数据并将其写入内存,超出了gets的范围。没有任何花哨的缓冲或交互作用发生-只是在未为此分配的内存上进行写操作。它可能破坏了程序中的某些内容。但是看来您很“幸运”,因为该错误并没有立即中断程序,并且数据停在那里,直到word可以从内存中读取它并将其写入输出为止。

但是,您永远不要期望这种行为。之所以能做到这一点,是因为您有一个非常简单的程序,它对内存没有任何其他作用。在具有许多对象和活动的更复杂的程序中,溢出缓冲区更有可能以多种方式破坏程序。


0
投票

这是puts的确切问题;一旦读取6个字符,它将将不会停止,它将一直读取直到看到换行符,并在gets缓冲区结束后立即将这些字符分配给内存。这就是缓冲区溢出is。如果在word缓冲区之后的几个字节中没有任何important(例如堆栈帧的返回地址或另一个局部变量),则覆盖该内存不会导致obvious问题,和word会做几乎相同的事情-从puts 及其后的内存中读取,直到看到字符串终止符。

© www.soinside.com 2019 - 2024. All rights reserved.