#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void cpy(char *str) {
//char buffer[16];
char *buffer = malloc(16 * sizeof(char));
strcpy(buffer, str);
for (int i = 0; i < 300; i++) {
printf("buffer[%i]: %c n", i, buffer[i]);
}
}
int main() {
//char large_str[256];
char *large_str = malloc(256 * sizeof(char));
for (int i = 0; i < 256; i++) {
large_str[i] = 'A';
}
//large_str[255]= ' ';
cpy(large_str);
return 0;
}
当我在Cygwin中编译并运行它时,我得到buffer[0]
buffer[299]
大部分是空的。我确实在索引块周围得到了一些垃圾,例如buffer[252]
到buffer[264]
,以及从索引0
到23
的'A'
。但是当我把它改成
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char buffer[16];
void cpy(char *buffer, char *str) {
//char *buffer = malloc(16 * sizeof(char));
strcpy(buffer, str);
for (int i = 0; i < 300; i++) {
printf("buffer[%i]: %c n", i, buffer[i]);
}
}
int main() {
//char large_str[256];
char *large_str = malloc(256 * sizeof(char));
for (int i = 0; i < 256; i++) {
large_str[i] = 'A';
}
//large_str[255]= ' ';
cpy(buffer, large_str);
return 0;
}
然后它完美地工作。buffer[0]
buffer[255]
包含'A'
,其余为空。为什么会有差异?
您有两个主要问题,都会导致未定义的行为:
-
您不会在
large_str
中终止字符串。这意味着所有寻找终止符(如strcpy
(的字符串函数都将超出界限。 -
将一个非常大的字符串(如果没有终止符甚至更大(复制到一个小缓冲区中。这意味着您将超出小缓冲区的范围。
请记住,C 没有任何边界检查。
另请注意,这些问题在您的两个程序中都存在。
查看 strcpy Linux 手册页
strcpy(( 函数将 src 指向的字符串(包括终止空字节 ('\0'((复制到 dest 指向的缓冲区。字符串不能重叠,并且目标字符串目标必须足够大才能接收副本。当心缓冲区溢出!
您正在分配一个 16 大小的缓冲区,并尝试用一个 256 大小的缓冲区填充它。 strcpy 将超出该缓冲区的边界,从而导致未定义的行为。
此行中有一个缓冲区溢出:
strcpy(buffer, str);
我建议使用以下语法确定要传递给 memcpy 中的缓冲区多少字节:
memcpy(dest, source, numOfBytes)
注意:当 in 遇到字符串中的 NULL 时,memcpy 不会停止。 只有当它完成复制您想要的所有字节时。但是,您可以以一种有助于避免创建溢出的方式进行设置
。.exe:
memcpy(buffer, str, 16);
这将帮助您避免创建动态内存损坏,从而导致意外结果甚至使程序崩溃。