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

看板C_and_CPP (C/C++)作者 (就是愛希爾)時間11年前 (2015/01/26 12:23), 編輯推噓4(4028)
留言32則, 9人參與, 最新討論串1/1
最近在研究字串複製的使用(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

01/26 12:42, , 1F
不要學 strcpy, strncpy, 這只會增加你寫出 bug 的機率
01/26 12:42, 1F

01/26 13:10, , 2F
恩 現在都用snprintf 只是好奇為什麼src的位置會變
01/26 13:10, 2F

01/26 13:26, , 3F
給你五個格子你硬要塞10個東西進去壞掉了很奇怪嗎?
01/26 13:26, 3F

01/26 13:32, , 4F
有時候我也覺得過於追求這種不合法動作的原理其實沒必要
01/26 13:32, 4F

01/26 13:36, , 5F
這類的問題如過需要問"為什麼"那就不需要知道"為什麼"
01/26 13:36, 5F

01/26 13:36, , 6F
知道不要這樣胡搞就夠了
01/26 13:36, 6F

01/26 13:37, , 7F
有能力應用這種胡搞的人不會問這個問題
01/26 13:37, 7F

01/26 15:05, , 8F
把src的Address(&src)印出,在思考strcpy原型程式碼
01/26 15:05, 8F

01/26 15:06, , 9F
你就會發現*s1++會剛好修改到&src位址所存放的值
01/26 15:06, 9F

01/26 15:09, , 10F
目標記憶體比較小時會造成修改到不應更改的記憶體區塊
01/26 15:09, 10F

01/26 17:45, , 11F
你的 dest 要 6 個 char
01/26 17:45, 11F

01/26 18:17, , 12F
13戒之2
01/26 18:17, 12F

01/26 18:48, , 13F
overflow
01/26 18:48, 13F

01/26 18:53, , 14F
我也同意刻意研究這個沒什麼意義,因為本身就是不合法
01/26 18:53, 14F

01/26 18:54, , 15F
真想知道,要學的已經不是程式語言,而是資料結構,
01/26 18:54, 15F

01/26 18:55, , 16F
還有逆向工程,你才會知道說local variable在stack中
01/26 18:55, 16F

01/26 18:56, , 17F
是如何推疊的,才會知道overflow為什麼會改變ptr addr
01/26 18:56, 17F

01/26 18:56, , 18F
所以「有能力應用這種胡搞的人不會問這個問題」。
01/26 18:56, 18F

01/26 21:08, , 19F
我比較好奇的是為什麼你的address不是4的倍數
01/26 21:08, 19F

01/27 00:16, , 20F
char本來就沒alignment
01/27 00:16, 20F

01/27 08:01, , 21F
src是global address
01/27 08:01, 21F

01/27 08:05, , 22F
除非"ABCDE"也放到global(怪?),或沒貼出來的code還有什麼
01/27 08:05, 22F

01/27 08:47, , 23F
另一怪是dest是較小位址,方便問一下你的gcc版本和編譯參數?
01/27 08:47, 23F

01/27 10:03, , 24F
src正確應是const char * = "1234567890";'
01/27 10:03, 24F

01/27 10:04, , 25F
位址大小問題是因為他不是存在Stack與Heap
01/27 10:04, 25F

01/27 10:04, , 26F
01/27 10:04, 26F

01/27 14:38, , 27F
回樓上,dest在stack中比&src要小所以執行strcpy才會蓋到src
01/27 14:38, 27F

01/27 14:42, , 28F
從src=8040030看來後面0030是'0'和'\0',所以&src=bffa7e5c
01/27 14:42, 28F

01/27 14:43, , 29F
老gcc常把先宣告的dest放在stack底層就是高位址
01/27 14:43, 29F

01/27 14:44, , 30F
年輕gcc容易把char[?]放在stack底層,也是高位址
01/27 14:44, 30F

01/27 14:45, , 31F
但是現在dest是低位址,所以我覺得有趣
01/27 14:45, 31F

01/27 14:54, , 32F
&"1234567890"應該是在.data,沒別的原因應該不會配奇數位址
01/27 14:54, 32F
文章代碼(AID): #1KnS4msJ (C_and_CPP)
文章代碼(AID): #1KnS4msJ (C_and_CPP)