什么可能导致这个缓冲区溢出?

3

你好,我正在尝试编译以下代码,

#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 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: ========

我不明白这里是什么导致了缓冲区溢出。有人能帮我解决吗?谢谢。

3个回答

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";

这就是为什么当你在双引号中键入字符数组时,不必这样做。


4
问题在于strcpy假定它正在查看字符串。C语言的约定是,字符串以空字符结尾。而你的数组没有这个特点,所以strcpy不知道何时停止。
要解决此问题,请添加第四个空字符或使用strncpy。
缺少空终止符也会导致printf出现问题。

哦,我刚刚忽略了它。非常感谢。 - user379888

2

无论是 strcpy 还是 printf,都需要 C 风格的以 0 结尾的字符串。您的 char 数组没有以 0 结尾。

因此,这两个函数将在以下内存块中疯狂查找,直到找到 '\0' 字节为止。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接