为什么在执行memcpy时检测到堆栈崩溃?
我正在努力掌握memcpy到底是如何工作的,这就是我到目前为止所写的例子。 这将输出为为什么在执行memcpy时检测到堆栈崩溃?,c,memory-management,C,Memory Management,我正在努力掌握memcpy到底是如何工作的,这就是我到目前为止所写的例子。 这将输出为abcdexyz&vjunkcharacters 还有下面的消息 char test[]={"abcde"}; char* test1={"xyz"}; memcpy(test+5,test1,3); printf("%s",test); 这种情况背后的原因是什么?您的memcpy调用会破坏堆栈,这就是您看到该消息的原因。您正在将数据复制到测试数组的末尾,这是不允许的。您的me
abcdexyz&vjunkcharacters
还有下面的消息
char test[]={"abcde"};
char* test1={"xyz"};
memcpy(test+5,test1,3);
printf("%s",test);
这种情况背后的原因是什么?您的
memcpy
调用会破坏堆栈,这就是您看到该消息的原因。您正在将数据复制到测试
数组的末尾,这是不允许的。您的memcpy
调用会破坏堆栈,这就是您看到该消息的原因。您复制的数据超过了测试的末尾,这是不允许的。根本原因:
*** stack smashing detected ***: ./testcode terminated
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x45)[0xb7656dd5]
/lib/i386-linux-gnu/libc.so.6(+0xffd8a)[0xb7656d8a]
./testcode[0x8048797]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb75704d3]
./testcode[0x80483a1]
分配足够的内存空间,仅存储5个字符
char test[]={"abcde"};
将test1
指向的数据复制到分配的内存空间之外。
从技术上讲,以这种方式超出分配内存的界限进行写入是未定义的行为,这意味着任何事情都可能发生
实际发生了什么?
这里实际发生的是memcpy
将字符复制到分配的内存之外,从而覆盖标记字符数组结束的NULL
终止符test
此外,printf
从test
的起始地址读取内容,直到遇到一个随机的NULL
,从而打印出垃圾字符
解决方案:
在执行memcpy
之前,应确保目标缓冲区已分配足够的内存。由于您打算复制3个
字符,您的目标缓冲区test
应至少为:
memcpy(test+5,test1,3);
您可以简单地使用:
5 + 3 + 1 byte for NULL terminator = 9 bytes
根本原因:
*** stack smashing detected ***: ./testcode terminated
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x45)[0xb7656dd5]
/lib/i386-linux-gnu/libc.so.6(+0xffd8a)[0xb7656d8a]
./testcode[0x8048797]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb75704d3]
./testcode[0x80483a1]
分配足够的内存空间,仅存储5个字符
char test[]={"abcde"};
将test1
指向的数据复制到分配的内存空间之外。
从技术上讲,以这种方式超出分配内存的界限进行写入是未定义的行为,这意味着任何事情都可能发生
实际发生了什么?
这里实际发生的是memcpy
将字符复制到分配的内存之外,从而覆盖标记字符数组结束的NULL
终止符test
此外,printf
从test
的起始地址读取内容,直到遇到一个随机的NULL
,从而打印出垃圾字符
解决方案:
在执行memcpy
之前,应确保目标缓冲区已分配足够的内存。由于您打算复制3个
字符,您的目标缓冲区test
应至少为:
memcpy(test+5,test1,3);
您可以简单地使用:
5 + 3 + 1 byte for NULL terminator = 9 bytes
行memcpy(test+5,test1,3)代码>以简单的文字执行以下操作:
从数组“test”的最后一个元素开始,将3个字符从数组“test1”复制到那里,这基本上会在数组“test”的长度之外写入2个字符
因此,如果您只想使用“memcpy”,请定义第三个数组:
char test[9]="abcde";
行memcpy(test+5,test1,3)代码>以简单的文字执行以下操作:
从数组“test”的最后一个元素开始,将3个字符从数组“test1”复制到那里,这基本上会在数组“test”的长度之外写入2个字符
因此,如果您只想使用“memcpy”,请定义第三个数组:
char test[9]="abcde";
变量test1在内存中有4个字符,3个字符加上结束字符串终止符。试试这个:
char test[]="abcde";
char test1[]="xyz";
char output[sizeof(test) + sizeof(test1)];
memset(output, 0, sizeof(output));
memcpy(&output[0],test,5);
memcpy(&output[5],test1,3);
printf("%s",output);
变量test1在内存中有4个字符,3个字符加上结束字符串终止符。试试这个:
char test[]="abcde";
char test1[]="xyz";
char output[sizeof(test) + sizeof(test1)];
memset(output, 0, sizeof(output));
memcpy(&output[0],test,5);
memcpy(&output[5],test1,3);
printf("%s",output);
在没有额外缓冲区的情况下执行此操作
事实上,最直接的方法是避免复制:
char test[9]={"abcde"};
char* test1={"xyz"};
memcpy(test+5,test1,4);
使用strcpy和strcat执行此操作
请注意,在使用memcpy时,正确处理字符串的空终止有很多缺陷。要简化字符串的此过程,应执行以下操作
如果这些确实是字符串而不是随机字节,那么您应该坚持使用标准库的字符串函数。就是这样做的
#include <string.h>
#include <stdio.h>
int main() {
char a[] = "abcde";
char b[] = "xyz";
/* note that both strings add a '\0' termination */
char c[sizeof(a) + sizeof(b) - 1];
/* copy the content of a to c */
memcpy(c, a, sizeof(a));
/* copy the content of b to where a ends (concatenate the strings) */
memcpy(c + sizeof(a) - 1, b, sizeof(b));
/* note that the '\0' termination of the string is necessary to let
* functions like printf know where the string is over
*/
printf(c);
return 0;
}
#包括
#包括
int main(){
字符a[]=“abcde”;
字符b[]=“xyz”;
/*请注意,这两个字符串都添加了'\0'终止符*/
字符c[sizeof(a)+sizeof(b)-1];
/*将a的内容复制到c*/
strcpy(c,a);
/*将b的内容复制到a结束的位置(连接字符串)*/
strcat(c,b);
/*请注意,字符串的“\0”终止符是让
*printf等函数知道字符串的结束位置
*/
printf(c);
返回0;
}
了解字符串的大小
关于知道缓冲区的大小,请注意,通常不能简单地执行sizeof(字符串)
。如果将字符数组传递给函数,它将衰减为指针,此操作将不再返回数组的预期大小,而是返回指针的大小
对于字符串,您需要发出strlen(a_string)
,它扫描空终止的发生并返回字符串的长度(不包括终止)
对于包含随机数据的字符缓冲区(或需要写入的空缓冲区),这种方法也不起作用。您始终需要将缓冲区的大小作为附加参数传递。在没有附加缓冲区的情况下执行此操作
事实上,最直接的方法是避免复制:
char test[9]={"abcde"};
char* test1={"xyz"};
memcpy(test+5,test1,4);
使用strcpy和strcat执行此操作
请注意,在使用memcpy时,正确处理字符串的空终止有很多缺陷。要简化字符串的此过程,应执行以下操作
如果这些确实是字符串而不是随机字节,那么您应该坚持使用st