[問題] strcpy記憶體位址變掉

作者: HILL33LOVE (就是愛希爾)   2015-01-26 12:23:10
最近在研究字串複製的使用(strcpy, strncpy, memcpy, snprintf)
在strcpy的case中,有兩種情況下會Segmentation fault(程式碼1, 2)
問題.想請問在[程式碼1]為什麼src的大小超過dest的大小
會讓src的address變了呢? (由原本的0x8048af5到0x8040030)
而導致在strcpy的時候沒事,而在印src字串時導致Segmentation fault
謝謝!!
[程式碼1]
void test()
{
char dest[5] = "ABCDE";
char *src = "1234567890";
printf("Dest = %s, Address = %p\n", dest, dest);
printf("Src = %s, Address = %p\n", src, src);
strcpy(dest, src);
printf("======================================\n");
printf("[strcpy] Dest = %s, Address = %p\n", dest, dest);
printf("[strcpy] Src Address = %p\n", src);
printf("[strcpy] Src = %s\n", src);
}
[執行結果]
# ./a.out
Dest = ABCDE, Address = 0xbffa7e53
Src = 1234567890, Address = 0x8048af5
======================================
[strcpy] Dest = 1234567890, Address = 0xbffa7e53
[strcpy] Src Address = 0x8040030
Segmentation fault (core dumped)
[程式碼2]
char dest[5] = "ABCDE";
char src[10] = "1234567890";
strcpy(dest, src);
[執行結果2]
因為src沒有\0停下來 所以strcpy會導致複製src時會一直複製,而產生Segmentation
fault
E 5
D 4
C 3
B 2
Dest A 1
0
9
8
7
6
5
4
3
2
Src 1
[strcpy原型]
char *strcpy(char *s1, const char *s2)
{
char *s = s1;
while ((*s++ = *s2++) != 0) {
;
}
return (s1);
}
作者: Ebergies (火神)   2015-01-26 12:42:00
不要學 strcpy, strncpy, 這只會增加你寫出 bug 的機率
作者: HILL33LOVE (就是愛希爾)   2015-01-26 13:10:00
恩 現在都用snprintf 只是好奇為什麼src的位置會變
作者: azureblaze (AzureBlaze)   2015-01-26 13:26:00
給你五個格子你硬要塞10個東西進去壞掉了很奇怪嗎?
作者: wenyonba (射後不理很XX啊!!!!)   2015-01-26 13:32:00
有時候我也覺得過於追求這種不合法動作的原理其實沒必要
作者: azureblaze (AzureBlaze)   2015-01-26 13:36:00
這類的問題如過需要問"為什麼"那就不需要知道"為什麼"知道不要這樣胡搞就夠了有能力應用這種胡搞的人不會問這個問題
作者: anyoiuo   2015-01-26 15:05:00
把src的Address(&src)印出,在思考strcpy原型程式碼你就會發現*s1++會剛好修改到&src位址所存放的值目標記憶體比較小時會造成修改到不應更改的記憶體區塊
作者: Bencrie   2015-01-26 17:45:00
你的 dest 要 6 個 char
作者: shadow0326 (非議)   2015-01-26 18:17:00
13戒之2
作者: TobyH4cker (Toby (我要當好人))   2015-01-26 18:48:00
overflow我也同意刻意研究這個沒什麼意義,因為本身就是不合法真想知道,要學的已經不是程式語言,而是資料結構,還有逆向工程,你才會知道說local variable在stack中是如何推疊的,才會知道overflow為什麼會改變ptr addr所以「有能力應用這種胡搞的人不會問這個問題」。
作者: dirkc (3781615)   2015-01-26 21:08:00
我比較好奇的是為什麼你的address不是4的倍數
作者: azureblaze (AzureBlaze)   2015-01-27 00:16:00
char本來就沒alignment
作者: dirkc (3781615)   2015-01-27 08:01:00
src是global address除非"ABCDE"也放到global(怪?),或沒貼出來的code還有什麼
作者: anyoiuo   2015-01-27 10:03:00
src正確應是const char * = "1234567890";'位址大小問題是因為他不是存在Stack與Heap可以參考http://en.wikipedia.org/wiki/Data_segment
作者: dirkc (3781615)   2015-01-27 14:38:00
回樓上,dest在stack中比&src要小所以執行strcpy才會蓋到src從src=8040030看來後面0030是'0'和'\0',所以&src=bffa7e5c老gcc常把先宣告的dest放在stack底層就是高位址年輕gcc容易把char[?]放在stack底層,也是高位址但是現在dest是低位址,所以我覺得有趣&"1234567890"應該是在.data,沒別的原因應該不會配奇數位址

Links booklink

Contact Us: admin [ a t ] ucptt.com