看板 C_and_CPP 關於我們 聯絡資訊
※ 引述《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
james732:不過在C語言裡,有方便處理「非null結尾字串」的方法嗎? 07/01 11:14
james732:還是說這部份的輪子還是要自己做?如果用C的話... 07/01 11:14
tropical72:謝謝littleshan說明,不過有一點疑問是,若不用null標尾 07/01 11:37
tropical72:內容也含有null,這樣strlen,strtok,strchr..不都沒用了 07/01 11:38
tropical72:在c裡面代表再自己打造一份出來嗎?目前我想到的解決是, 07/01 11:39
tropical72:用mem~系列相關函式進行取代,但仍有一堆要改寫.. 07/01 11:40
james732:這就是我的疑問 XDD 07/01 11:43
littleshan:如果你的專案牽涉大量的字串處理,那根本不該用純C 07/01 12:05
littleshan:或是使用別人的string library如better string library 07/01 12:09
james732:better string library... 真是個好懂的名稱 XDDDD 07/01 12:22
tropical72:再請教,std::string 是否是以 null 標示結尾? 07/01 12:28
tropical72:另,應部份compiler(VC)也提供了wc/_mbs/系列函式,不知 07/01 12:30
tropical72:是否可避開這種問題?謝謝您的指教。 07/01 12:30
loveme00835:不是null結尾, 你用s[s.size()]回傳的是模版引數charT 07/01 13:02
loveme00835:型態的物件(呼叫預設建構子), '\0'是湊巧而已, 要和C 07/01 13:04
loveme00835:函式接合請愛用 string::data、string::c_str 07/01 13:04
tropical72:謝謝loveme00835解惑 *^_^* 07/01 13:12
angleevil:strlen是可以算無null結尾的字串長度喔,其他應該就不行 07/01 14:48
LPH66:樓上不對吧...strlen只看'\0'當字串結束 07/01 15:48
LPH66:所以非'\0'結尾的字串去做strlen就會出事.... 07/01 15:48
james732:我也很疑惑,angleevil能否給個範例呢? 07/01 15:49
angleevil:也沒範例,這是有一天我忘記加\0,然後用strlen去算長度 07/01 16:44
angleevil:而且不是一兩次了,這應該是無解狀況吧! 07/01 16:45
james732:那大概是你的陣列後面有0吧 07/01 16:47
james732:像這種情況 http://pastie.org/2148973 不加 '\0' 也ok 07/01 16:48
angleevil:printf("%d\n", strlen("1234567890"));<-- 07/01 17:59
littleshan:string literal 都是 null-terminated 07/01 18:17
angleevil:@@ 07/01 18:19
purpose:你用 debugger 觀察 strlen("1234567890") 的 arg 所在處 07/01 18:33
purpose:該處記憶體應該除了 1234567890 以外還有 \0 在最後面 07/01 18:34
firejox:似乎沒有人提到strn系列.... 07/01 19:05
firejox:自寫link list來處理字串應該也可以吧.... 07/01 19:10
littleshan:strn要傳進的那個n就是需要額外處理的字串長度 07/01 23:36
littleshan:另外link list在index以及取用substring會很沒效率 07/01 23:37
firejox:substring倒是還好 index是因為不是相鄰所以很麻煩... 07/01 23:58
littleshan:若不會更改原值,對陣列取substring是constant time 07/02 00:02
firejox:應該是說要拿substring做什麼 比方說做tree之類的 07/02 16:00