您好我正在尝试编译以下代码,
#include <stdio.h>
#include <string.h>
int main()
{
int i;
char a[3] = {'1', '2', '3'},b[3] = {'3', '2', '1'};
strcpy(a,b);
for(i=0; i<3; i++)
printf("%s",a);
return 0;
}
但我收到以下错误(Buffer Overflow
)
*** buffer overflow detected ***: ./prog terminated
======= Backtrace: =========
/lib/libc.so.6(__fortify_fail+0x48)[0xb7653ae8]
/lib/libc.so.6[0xb7651b30]
/lib/libc.so.6(__strcpy_chk+0x44)[0xb7650e14]
./prog[0x80484c9]
./prog[0x80483c1]
======= Memory map: ========
现在我没有得到导致缓冲区溢出的原因。有人可以帮帮我吗? 非常感谢。
答案 0 :(得分:11)
此:
char a[4] = {'1', '2', '3'},b[4] = {'3', '2', '1'};
创建两个分别包含字符串“123”和“321”的字符数组,但不是以NULL结尾。按照惯例,C字符串必须以NULL结尾,否则操作它们的函数(例如strcpy
)不知道它们的结束位置。您需要这样做才能为它们提供NULL终结符:
char a[4] = {'1', '2', '3', 0}, b[4] = {'3', '2', '1', 0};
^--------------------------^----> NULL terminators
(0 or '\0', NOT '0')
还要注意,数组的大小从 3 更改为 4 以容纳结尾NULL。您还可以保留大小,让编译器通过查看您在初始化列表中放入的内容来确定生成数组的大小:
char a[] = {'1', '2', '3', 0}, b[] = {'3', '2', '1', 0}; // sizes are left out
当您输入如下字符串文字时:
char a[] = "hello";
编译器最后会为你添加NULL,所以你真正做的是:
char a[] = "hello\0";
这就是为什么在用双引号键入字符数组时不必这样做的原因。
答案 1 :(得分:4)
问题是strcpy假设它正在查看字符串。字符串的C约定是它们以空字符结尾。你的数组不是,因此strcpy不知道何时停止。
要解决此问题,请添加第4个空字符或使用strncpy。
缺少空终止也会在printf时出现问题。
答案 2 :(得分:2)
strcpy
和printf
期望c-style 0
- 终止字符串。您的char
数组不是0
- 终止。
因此,两个函数都会在以下内存块中严重破坏,直到找到'\ 0'字节为止。