[英]Why am I getting stack smashing detected when doing memcpy?
char test[]={"abcde"};
char* test1={"xyz"};
memcpy(test+5,test1,3);
printf("%s",test);
我試圖了解memcpy的工作原理,這是我到目前為止編寫的示例。 這將輸出作為abcdexyz&vjunkcharacters
和以下消息。
*** 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]
這種情況背后的原因是什么?
根本原因:
char test[]={"abcde"};
分配足夠的內存空間以僅存儲5
字符。
memcpy(test+5,test1,3);
將test1
指向的數據復制到分配的內存空間之外。
從技術上講,以這種方式寫超出已分配內存的邊界是Undefined Behavior ,這意味着可能發生任何事情。
實際發生了什么?
實際發生的是memcpy
字符復制到分配的內存之外,從而覆蓋了NULL
終止符,該終止符標志着字符數組test
結束。
此外, printf
從test
起始地址讀取內容,直到遇到隨機NULL
從而打印出垃圾字符。
解:
在執行memcpy
之前,應確保目標緩沖區已分配足夠的內存。 由於您打算復制3
字符,因此目標緩沖區test
應至少:
5 + 3 + 1 byte for NULL terminator = 9 bytes
您可以簡單地使用:
char test[9]="abcde";
您的memcpy
調用確實粉碎了堆棧,這就是為什么您看到該消息的原因。 您正在復制test
數組末尾的數據,這是不允許的。
無需額外的緩沖
實際上,最直接的方法是避免復制:
#include <string.h>
#include <stdio.h>
int main() {
char a[] = "abcde";
char b[] = "xyz";
printf("%s%s\n", a, b);
return 0;
}
用memcpy做
memcpy將src
n
個字節復制到dest
。 您需要自己正確跟蹤復制字符串的空終止字節。
#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;
}
用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 */
strcpy(c, a);
/* copy the content of b to where a ends (concatenate the strings) */
strcat(c, 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;
}
知道琴弦的大小
關於知道緩沖區的大小,請注意,通常不能簡單地執行sizeof(a_string)
。 如果將字符數組傳遞給函數,則它會衰減為指針,並且此操作不再返回數組的預期大小,而是返回指針的大小。
對於字符串,您需要發出strlen(a_string)
來掃描空終止符的出現並返回字符串的長度(不包括終止符)。
對於包含隨機數據的字符緩沖區(或需要寫入的空緩沖區),此方法也不起作用。 您始終需要將緩沖區的大小作為附加參數傳遞。
行memcpy(test+5,test1,3);
用簡單的話做以下事情:
“從數組“ test”的最后一個元素開始,然后從數組“ test1”復制3個字符到那里”,這基本上寫了2個字符,超出了數組“ test”的長度。
因此,如果您只想玩'memcpy',請定義第三個數組:
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[9]={"abcde"};
char* test1={"xyz"};
memcpy(test+5,test1,4);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.