任何人都可以解释为什么输出超过分配的内存?

时间:2014-10-02 06:04:30

标签: c++ c

#include <stdio.h>

int main(void) {
    char arr[10];
    gets(arr);//let's suppose input is "abcdefgshsdfhdsfsh" 
    printf("%s",arr);//output come is same as input but the allocated arr have 10 bytes memory
                        //and can store only ten characters but how come it's possible i am getting output 
                        //more than 10 character
    return 0;
}

输出背后的原因是什么?任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:2)

因为在从stdin获取字节并将它们放在某处时,gets不会进行任何检查。一个简单的例子:

char array1[] = "12345";
char array2[] = "67890";

gets(array1);

现在,首先您可以输入您想要的字符数,gets不会关心它。其次,你放置它们的数组大小的字节数(在本例中为array1)将覆盖它们在内存中找到的任何内容,因为gets将写入它们。在前面的例子中,这意味着如果您输入“abcdefghijklmnopqrts”可能,不可预测,它也会覆盖array2或其他任何内容。

该功能不安全,因为它假定输入一致。千万不要用它!

更安全的方法是fgets()

所以,你想避免getsfgets将始终读取新行,如果缓冲区大到足以容纳它(这会让你知道缓冲区何时太小而且有更多的行等待读取)。如果你想要fgets之类的东西不会读取新行(丢失指示太小的缓冲区),你可以使用fscanf进行扫描集转换,如:“%N [ ^ \ n]“,其中'N'被缓冲区大小替换为-1。

使用fgets阅读后,从缓冲区中删除尾随换行符的一种简单(如果很奇怪)方法是:strtok(buffer, "\n");这不是strtok的用法。 ,但我用这种方式比预期的方式更常用(我通常会避免)。

来源:从我保存的问题中复制。

答案 1 :(得分:0)

未定义的行为意味着程序不遵循该语言的规则,并且编译器不会对结果行为做出任何承诺。

因此,当您在数组的末尾写入时,这是未定义的行为,该语言不会保证它会让您知道错误。它似乎可行,可能会崩溃。今天可能会做一件事,明天可能做另一件事。

有点像把50磅的东西放在一个额定容量为20磅的架子上。也许它会坚持下去,也许它会立即崩溃。也许它会坚持到你拿走一些东西然后崩溃了。

答案 2 :(得分:-2)

C字符串(类型char的数组)需要一个终止空字节来指示字符串的结尾。当正在处理字符串的字节时,例如printf(),当达到null时,该函数将停止处理这些字节。由于超出了数组的长度(并且在与数组相邻的任何内存中,最后的空字节已经放置在距离数组起点10个字节以外),因此该函数在未定义的字节数时继续执行印刷。