2010年2月5日 星期五

字串操作常見問題

字串操作常見問題

[轉貼] iceis' Blog

[By JHF 學長]
1.
char *str;
str = "string";
這個是錯誤的, 因為str是一個指標, 他是指向記憶體中某個位址,
而"string"是一個常數字串, 常數在記憶體中並沒有一個專屬的記憶體
所以, 會在compiling time出錯....

如果要一開始就給予一個常數字串, 應該用:
char str[] = "string"
這樣的指令, 則str就表示"string"這個字串的開頭位址....

如果被給予的字串會因程式的執行而產生改變, 例如以下的例子....
2.
char *str;
strcpy(str, "string");

這個也是錯誤的, 因為strcpy()所做的事情是將第二個參數的字串一個
一個拷貝到第一個參數所指的空間, 但是, 第一個參數到目前為止它還
只是一個被宣告出來的字串指標喔....

有以下兩種做法可以達到相同的效果:
a.
char str[1024] // 個人比較喜歡開4096的空間出來暴力玩....
strcpy(str, "string");

b.
char *str;
str = (char*)malloc(sizeof(char) * 1024);
strcpy(str, "string");

雖然效果相同但是實際使用時的意義卻不大一樣, a.的做法是限死的,
如果你拷貝的字串超過str的大小, 那在strcpy裡頭會出錯....這一點
可以藉由strncpy()這個函式來彌補這個缺點

b.的做法則可以動態調整大小, 不過如果是以下的操作的時候, 有一些
細節得注意:
char *str;
str = (char*)malloc(sizeof(char) * strlen("string"));
strcpy(str, "string");
str = strdup("second string");

這個問題在於: 第二行的code已經先在記憶體要了一塊空間, 然後將
"string"拷貝進去之後, 第四行使用strdup, 此時str會指向一塊內容
為 "second string"的字串....唔, 好像沒問題對吧? 但是你先前要
的那個字串"string"卻沒有人理囉....

是的, strdup()會幫你做到: 在記憶體中要一塊跟傳入的參數同樣大小的
空間, 然後幫你把字串拷貝過去, 然後回傳字串指標....所以做的事情
跟第二第三行差不多....但是如果不小心使用的話, 你的記憶體就會這樣
一塊一塊的被吃掉....一般小程式是看不出它的威脅....如果你的程式是
專做字串處理的, 例如parse client端傳來的資料等等, 這些被蠶食的記
憶體空間遲早會被用光....然後就....crash....

ref:
iceis' Blog

2 則留言:

  1. 宣告字串
    char str[] = "string";
    or
    char *str = "string";
    都可以,但較正確是前者!

    使用malloc記得用完要free
    還有作者說開4096暴力玩法...PC可以這樣玩
    但是embbeded這樣很浪費記憶體空間!

    回覆刪除
  2. 忘了補充...malloc出來的空間有點像是全域變數
    只要你沒free他就一直在,而且任何function都可以用,但得知道它的address!
    大多人都不敢用,因為常常忘了free,忘了free很容易
    造成記憶體亂掉,因為我是受害者!ㄏ~

    回覆刪除