2007年10月30日

Socket Programming in C 常犯的錯誤

在一個簡單的網路程式,似乎有滿多人都會這樣寫(轉自對岸教學網站):

char tmp[32];
memset( tmp, '\0', sizeof(tmp));
int ret = recv( sock, tmp, sizeof(tmp), 0 );
printf("%s\n", tmp);

把 buffer 填滿固然是一件好事,但是字串填滿之後,結果沒有\0了
就會發生意想不到的事情,可能會出現程式記憶體存取違規的問題
( 字元陣列的結尾正常結束都要有個 \0 才是正確的 )

假設我們不看 ret 回傳收到多大的資料,考慮使用 strcat 來把回傳的 buffer
串到更大的 buffer 字元陣列,應該要扣掉1來使用,避免發生記憶體存取違規!

char tmp[32];
int ret;
if( (ret = recv( sock, tmp, sizeof(tmp) - 1, 0 ) ) > 0 ) {
    tmp[ret] = 0x0;
    printf("%s\n", tmp);
}

PS. 經多名友人反應,本文再度稍做補充,順便補上錯誤檢查,避免造成更多誤會 XD

基本上這篇很單純寫給初學者看的,平常實甚忙碌,閒暇時逛網看到對岸常見教學
網站文章,出現了離譜的範例,而很多人又習慣拷貝教學文章四處轉貼。

這篇文章的主旨不外乎探討一般簡單的範例會把收到的資料透過 printf 出來或做 strcat
而在這個時候如果字元陣列尾端沒有 \0 就會引起 Access Violation 記憶體存取違規。

對於 memset 的操作,也是原本的文章這樣寫,純粹只是直接拷貝沿用舉例,
很明顯是 O(n) 的時間複雜度,當然不好,但這根本不是我發此文討論的重點呀 XDD
另外,這篇也不是要探討傳輸 binary data 的應用,更與 HTTP 協定無關。



Posted by kuso_cc at 樂多Roodo! │20:40 │回應(1)引用(0)程式設計
樂多分類:網路/3C 工具:加入樂多書籤編輯本文
Ads by Roodo! 

引用URL

http://cgi.blog.roodo.com/trackback/4392251
回應文章
Hi 莉洛,

我寫了一段文字說明這篇文中問題, 請參考 re: Socket Programming in C 常犯的錯誤.
Posted by fr3@K at 2008年04月22日 17:07