为什么数组可以存储比它应该更多的数据?

时间:2017-06-01 03:57:31

标签: c

以下C代码有 char str [3]; ,它应该只存储3个字符?

然而,当我编译并运行程序时,它似乎可以存储更多。

我只得到"分段错误"我输入" ABCDEFGHIJKLMNOPQRSTUVWXY"这显然超过3个字符。

我可以知道为什么吗?

p / s:是的,我知道"得到"功能很危险,不建议使用。我只是好奇为什么它可以保留更多的数据。

user@box:~/c$ cat -n putsgets.c 
     1  #include <stdio.h>
     2
     3  int main()
     4  {
     5          char str[3];
     6          puts("Enter a line of text: ");
     7          gets(str);
     8          puts("\nYou entered: ");
     9          puts(str);
    10          return 0;
    11  }
user@box:~/c$ 
user@box:~/c$ gcc putsgets.c -o putsgets
putsgets.c: In function ‘main’:
putsgets.c:7:2: warning: implicit declaration of function ‘gets’ [-Wimplicit-function-declaration]
  gets(str);
  ^~~~
/tmp/cclFmZp2.o: In function `main':
putsgets.c:(.text+0x1f): warning: the `gets' function is dangerous and should not be used.
user@box:~/c$ 
user@box:~/c$ ./putsgets 
Enter a line of text: 
ABC

You entered: 
ABC
user@box:~/c$ ./putsgets 
Enter a line of text: 
ABCD    

You entered: 
ABCD
user@box:~/c$

下一步

user@box:~/c$ ./putsgets 
Enter a line of text: 
ABCDE     

You entered: 
ABCDE
user@box:~/c$ ./putsgets 
Enter a line of text: 
ABCDE

You entered: 
ABCDE
user@box:~/c$ ./putsgets 
Enter a line of text: 
ABCDEF

You entered: 
ABCDEF

user@box:~/c$ ./putsgets 
Enter a line of text: 
ABCDEFGHIJKLMN

You entered: 
ABCDEFGHIJKLMN

最后,当我输入ABCDEFGHIJKLMNOPQRSTUVWXY(最后一行)时发生了分段错误

user@box:~/c$ ./putsgets 
Enter a line of text: 
ABCDEFGHIJKLMNOPQRSTU

You entered: 
ABCDEFGHIJKLMNOPQRSTU
user@box:~/c$ ./putsgets 
Enter a line of text: 
ABCDEFGHIJKLMNOPQRSTUVWXYZ

You entered: 
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Segmentation fault
user@box:~/c$ ./putsgets 
Enter a line of text: 
ABCDEFGHIJKLMNOPQRSTUVWXY   

You entered: 
ABCDEFGHIJKLMNOPQRSTUVWXY
Segmentation fault
user@box:~/c$ 

3 个答案:

答案 0 :(得分:5)

您可能知道,C不会检查内存安全性。但是,像valgrind这样的公用事业确实可以帮助解决这个问题。

您的操作系统为您的程序提供了比它请求的内存更多的内存,并且只有当您走出其中一个内存时才会发现分段错误。

How does a segmentation fault work internally (kernel/hardware)?

答案 1 :(得分:1)

它的未定义行为,因为C和C ++不检查数组绑定。

答案 2 :(得分:1)

在C中,您可以向数组添加比声明更多的cbaracters,因为不会执行运行时检查。你所做的就是缓冲区溢出。

如果此类代码通过网络连接接受数据,则黑客可以利用它来运行任意机器代码!

但是,在java和C#中执行运行时检查并且缓冲区溢出会导致OutOfRangeExeption。这些检查由java虚拟机执行。

好问题,并保持好奇心。