看板 C_and_CPP 關於我們 聯絡資訊
最近在研究字串複製的使用(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); } -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 114.32.33.23 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1422246192.A.D93.html
Ebergies: 不要學 strcpy, strncpy, 這只會增加你寫出 bug 的機率 01/26 12:42
HILL33LOVE: 恩 現在都用snprintf 只是好奇為什麼src的位置會變 01/26 13:10
azureblaze: 給你五個格子你硬要塞10個東西進去壞掉了很奇怪嗎? 01/26 13:26
wenyonba: 有時候我也覺得過於追求這種不合法動作的原理其實沒必要 01/26 13:32
azureblaze: 這類的問題如過需要問"為什麼"那就不需要知道"為什麼" 01/26 13:36
azureblaze: 知道不要這樣胡搞就夠了 01/26 13:36
azureblaze: 有能力應用這種胡搞的人不會問這個問題 01/26 13:37
anyoiuo: 把src的Address(&src)印出,在思考strcpy原型程式碼 01/26 15:05
anyoiuo: 你就會發現*s1++會剛好修改到&src位址所存放的值 01/26 15:06
anyoiuo: 目標記憶體比較小時會造成修改到不應更改的記憶體區塊 01/26 15:09
Bencrie: 你的 dest 要 6 個 char 01/26 17:45
shadow0326: 13戒之2 01/26 18:17
TobyH4cker: overflow 01/26 18:48
TobyH4cker: 我也同意刻意研究這個沒什麼意義,因為本身就是不合法 01/26 18:53
TobyH4cker: 真想知道,要學的已經不是程式語言,而是資料結構, 01/26 18:54
TobyH4cker: 還有逆向工程,你才會知道說local variable在stack中 01/26 18:55
TobyH4cker: 是如何推疊的,才會知道overflow為什麼會改變ptr addr 01/26 18:56
TobyH4cker: 所以「有能力應用這種胡搞的人不會問這個問題」。 01/26 18:56
dirkc: 我比較好奇的是為什麼你的address不是4的倍數 01/26 21:08
azureblaze: char本來就沒alignment 01/27 00:16
dirkc: src是global address 01/27 08:01
dirkc: 除非"ABCDE"也放到global(怪?),或沒貼出來的code還有什麼 01/27 08:05
dirkc: 另一怪是dest是較小位址,方便問一下你的gcc版本和編譯參數? 01/27 08:47
anyoiuo: src正確應是const char * = "1234567890";' 01/27 10:03
anyoiuo: 位址大小問題是因為他不是存在Stack與Heap 01/27 10:04
anyoiuo: 可以參考http://en.wikipedia.org/wiki/Data_segment 01/27 10:04
dirkc: 回樓上,dest在stack中比&src要小所以執行strcpy才會蓋到src 01/27 14:38
dirkc: 從src=8040030看來後面0030是'0'和'\0',所以&src=bffa7e5c 01/27 14:42
dirkc: 老gcc常把先宣告的dest放在stack底層就是高位址 01/27 14:43
dirkc: 年輕gcc容易把char[?]放在stack底層,也是高位址 01/27 14:44
dirkc: 但是現在dest是低位址,所以我覺得有趣 01/27 14:45
dirkc: &"1234567890"應該是在.data,沒別的原因應該不會配奇數位址 01/27 14:54