strcpy 无法在动态分配的 char 数组中正常工作


#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],以及从索引023'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',其余为空。为什么会有差异?

您有两个主要问题,都会导致未定义的行为

  1. 您不会在large_str中终止字符串。这意味着所有寻找终止符(如strcpy(的字符串函数都将超出界限。

  2. 将一个非常大的字符串(如果没有终止符甚至更大(复制到一个小缓冲区中。这意味着您将超出小缓冲区的范围。

请记住,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);

这将帮助您避免创建动态内存损坏,从而导致意外结果甚至使程序崩溃。