十三誡增修--04:你不可以試圖用 char* 去更改一個"字串常數"

作者: wtchen (沒有存在感的人)   2016-05-14 16:45:03
04. 你不可以試圖用 char* 去更改一個"字串常數"
試圖去更改字串常數(string literal)的結果會是undefined behavior。
錯誤例子:
char* pc = "john"; /* pc 現在指著一個字串常數 */
*pc = 'J'; /* undefined behaviour,結果無法預測*/
pc = "jane"; /* 合法,pc指到在別的位址的另一個字串常數*/
/* 但是"john"這個字串還是存在原來的地方不會消失*/
因為char* pc = "john"這個動作會新增一個內含元素為"john\0"的static char[5],
然後pc會指向這個static char的位址(通常是唯讀)。
若是試圖存取這個static char[],Standard並沒有定義結果為何。
pc = "jane" 這個動作會把 pc 指到另一個沒在用的位址然後新增一個
內含元素為"jane\0"的static char[5]。
可是之前那個字串 "john\n" 還是留在原地沒有消失。
通常編譯器的作法是把字串常數放在一塊read only(.rdata)的區域內,
此區域大小是有限的,所以如果你重複把pc指給不同的字串常數,
是有可能會出問題的。
正確例子:
char pc[] = "john"; /* pc 現在是個合法的陣列,裡面住著字串 john */
/* 也就是 pc[0]='j', pc[1]='o', pc[2]='h',
pc[3]='n', pc[4]='\0' */
*pc = 'J';
pc[2] = 'H';
說明:字串常數的內容應該要是"唯讀"的。您有使用權,但是沒有更改的權利。
若您希望使用可以更改的字串,那您應該將其放在合法空間
錯誤例子:
char *s1 = "Hello, ";
char *s2 = "world!";
/* strcat() 不會另行配置空間,只會將資料附加到 s1 所指唯讀字串的後面,
造成寫入到程式無權碰觸的記憶體空間 */
strcat(s1, s2);
正確例子(2):
/* s1 宣告成陣列,並保留足夠空間存放後續要附加的內容 */
char s1[20] = "Hello, ";
char *s2 = "world!";
/* 因為 strcat() 的返回值等於第一個參數值,所以 s3 就不需要了 */
strcat(s1, s2);
C++對於字串常數的嚴格定義為const char* 或 const char[]。
但是由於要相容C,char* 也是允許的寫法(不建議就是)。
不過,在C++試圖更改字串常數(要先const_cast)一樣是undefined behavior。
const char* pc = "Hello";
char* p = const_cast<char*>(pc);
p[0] = 'M'; // undefined behaviour
備註:
由於不加const容易造成混淆,
建議不管是C還是C++一律用 const char* 定義字串常數。
補充資料:
http://en.cppreference.com/w/c/language/string_literal
http://en.cppreference.com/w/cpp/language/string_literal
字串函數相關:#1IOXeMHX
undefined behavior : 精華區 z -> 3 -> 3 -> 23
作者: EdisonX (卡卡獸)   2016-05-14 22:12:00
#1IOXeMHX (C_and_CPP) 要修的話,這篇可以當後半段 ?
作者: Rollnmeow (OHAI)   2016-05-14 22:34:00
有錯字 第一個undefined behavior打成了behavoir
作者: Caesar08 (Caesar)   2016-05-14 22:46:00
需要補充undefined behavior是甚麼意思嗎?
作者: EdisonX (卡卡獸)   2016-05-14 23:35:00
那就得看 .rdata 有多大了, 不過避開弄爆的方法很多 , 但用這特性也可以做一些奇淫怪技。
作者: wtchen (沒有存在感的人)   2016-05-14 23:40:00
可以教一下這邪惡的技巧嗎?
作者: EdisonX (卡卡獸)   2016-05-14 23:43:00
作者: wtchen (沒有存在感的人)   2016-05-14 23:48:00
居然還有這招....

Links booklink

Contact Us: admin [ a t ] ucptt.com