Re: [問題] strcpy的函數定義

看板C_and_CPP (C/C++)作者 (我要加入劍道社!)時間15年前 (2011/07/01 11:11), 編輯推噓5(5032)
留言37則, 8人參與, 最新討論串4/4 (看更多)
※ 引述《tropical72 (藍影)》之銘言: : --------- : 我認為 strcpy 有個地方其實沒設計的很好 這東西是舊時代的產物了 現在寫 C++ 應該用 std::string 寫 C 的話就用 strncpy 不然就是平常多積些陰德吧 : 這段 code 會發生什麼事確實沒人會知道, : 其實還是有極少機會會發生 - strcat 幾次、再 strcpy 就發生了, : 大多都是出現 stack overflow 問題, : 且這問題未必具有重現性,以我「僥倖」跑過後,得到的結果如下 : src:345678901234567890... : des:123456789012345678901234567890... : ptr:123456789012345678901234567890... : 最後發現:用 strcpy 在這時候 (當然是我幹了傻事的結果),des!=src , : 更離譜的是,const src 也被吃掉了。而 ptr 卻仍沒防呆作用? 因為 src 和 des 都配置在 stack 上,而且 des 位於低位址 所以對 des 的寫入如果超出長度 就會寫到 src 上面 : assert(strcmp(strcpy(des, src), src); : 還要再加這段的話,那幹嘛不一開始在有問題的時候就傳回 NULL, : 還要硬指向 des? 這就是重點了...它的回傳值不是讓你判斷是否成功用的 因為 strcpy 接的是兩個 char* 而沒有這兩塊 buffer 的長度 所以它根本無法判斷字串複製是否會造成 buffer overrun 直接講結論 「不要用 null-terminated string 來儲存你的字串」 因為 1. 長度資訊很重要,而且經常會用到。一直用 strlen 會大幅降低效率 2. 不使用 null 來標示結尾,字串內容才能包含 null : 嗯,我想 M$ 所有 _s 系列 (strcpy_s, strcmp_s...) 函式應是這樣出來的。 : 淺見,歡迎指正。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 114.32.15.163

07/01 11:14, , 1F
不過在C語言裡,有方便處理「非null結尾字串」的方法嗎?
07/01 11:14, 1F

07/01 11:14, , 2F
還是說這部份的輪子還是要自己做?如果用C的話...
07/01 11:14, 2F

07/01 11:37, , 3F
謝謝littleshan說明,不過有一點疑問是,若不用null標尾
07/01 11:37, 3F

07/01 11:38, , 4F
內容也含有null,這樣strlen,strtok,strchr..不都沒用了
07/01 11:38, 4F

07/01 11:39, , 5F
在c裡面代表再自己打造一份出來嗎?目前我想到的解決是,
07/01 11:39, 5F

07/01 11:40, , 6F
用mem~系列相關函式進行取代,但仍有一堆要改寫..
07/01 11:40, 6F

07/01 11:43, , 7F
這就是我的疑問 XDD
07/01 11:43, 7F

07/01 12:05, , 8F
如果你的專案牽涉大量的字串處理,那根本不該用純C
07/01 12:05, 8F

07/01 12:09, , 9F
或是使用別人的string library如better string library
07/01 12:09, 9F

07/01 12:22, , 10F
better string library... 真是個好懂的名稱 XDDDD
07/01 12:22, 10F

07/01 12:28, , 11F
再請教,std::string 是否是以 null 標示結尾?
07/01 12:28, 11F

07/01 12:30, , 12F
另,應部份compiler(VC)也提供了wc/_mbs/系列函式,不知
07/01 12:30, 12F

07/01 12:30, , 13F
是否可避開這種問題?謝謝您的指教。
07/01 12:30, 13F

07/01 13:02, , 14F
不是null結尾, 你用s[s.size()]回傳的是模版引數charT
07/01 13:02, 14F

07/01 13:04, , 15F
型態的物件(呼叫預設建構子), '\0'是湊巧而已, 要和C
07/01 13:04, 15F

07/01 13:04, , 16F
函式接合請愛用 string::data、string::c_str
07/01 13:04, 16F

07/01 13:12, , 17F
謝謝loveme00835解惑 *^_^*
07/01 13:12, 17F

07/01 14:48, , 18F
strlen是可以算無null結尾的字串長度喔,其他應該就不行
07/01 14:48, 18F

07/01 15:48, , 19F
樓上不對吧...strlen只看'\0'當字串結束
07/01 15:48, 19F

07/01 15:48, , 20F
所以非'\0'結尾的字串去做strlen就會出事....
07/01 15:48, 20F

07/01 15:49, , 21F
我也很疑惑,angleevil能否給個範例呢?
07/01 15:49, 21F

07/01 16:44, , 22F
也沒範例,這是有一天我忘記加\0,然後用strlen去算長度
07/01 16:44, 22F

07/01 16:45, , 23F
而且不是一兩次了,這應該是無解狀況吧!
07/01 16:45, 23F

07/01 16:47, , 24F
那大概是你的陣列後面有0吧
07/01 16:47, 24F

07/01 16:48, , 25F
像這種情況 http://pastie.org/2148973 不加 '\0' 也ok
07/01 16:48, 25F

07/01 17:59, , 26F
printf("%d\n", strlen("1234567890"));<--
07/01 17:59, 26F

07/01 18:17, , 27F
string literal 都是 null-terminated
07/01 18:17, 27F

07/01 18:19, , 28F
@@
07/01 18:19, 28F

07/01 18:33, , 29F
你用 debugger 觀察 strlen("1234567890") 的 arg 所在處
07/01 18:33, 29F

07/01 18:34, , 30F
該處記憶體應該除了 1234567890 以外還有 \0 在最後面
07/01 18:34, 30F

07/01 19:05, , 31F
似乎沒有人提到strn系列....
07/01 19:05, 31F

07/01 19:10, , 32F
自寫link list來處理字串應該也可以吧....
07/01 19:10, 32F

07/01 23:36, , 33F
strn要傳進的那個n就是需要額外處理的字串長度
07/01 23:36, 33F

07/01 23:37, , 34F
另外link list在index以及取用substring會很沒效率
07/01 23:37, 34F

07/01 23:58, , 35F
substring倒是還好 index是因為不是相鄰所以很麻煩...
07/01 23:58, 35F

07/02 00:02, , 36F
若不會更改原值,對陣列取substring是constant time
07/02 00:02, 36F

07/02 16:00, , 37F
應該是說要拿substring做什麼 比方說做tree之類的
07/02 16:00, 37F
文章代碼(AID): #1E3JhasO (C_and_CPP)
文章代碼(AID): #1E3JhasO (C_and_CPP)