我寫程式的原則是這樣,

除非系統相依的功能,否則在非必要的情況下,我盡可能的使用標準函式庫裡面的東西,

而不是_GNU_SOURCE之類的實作。

今天review了另一個人的code,

說實在那code寫得滿愚蠢的,至於有多愚蠢容後解釋。

他想要做這樣的動作:

先將一段未知長度的資料(可能非常非常的長,

而大部份的case那段資料的長度都很短,只有在鮮少的機會出現極長的資料,

所以如果我們每次都allocate一塊大記憶體來用,這樣是不經濟的)轉成一個長字串,

然後再將該長字串透過UNIX Socket傳給另一個程式。

這樣的動作其實有很好的函式可以用像是dprintf或是vdprintf,

但是在uclibc的函作當中,這樣寫出去的東西可能是"分兩次"寫出去的,

而大部份的人寫程式的習慣也是一來一往的通訊而已,不會分段收。

所以這樣的寫法在很多case上是有問題,結論我也不可以用dprintf。

然後我接手的那個程式很妙,他會malloc(512),至於為什麼要用malloc一個固定長度我一點也不懂,

於是他在處理超過512個byte的結果時就出問題了,程式就當掉… 

事實在linux的libc實作有很多方便的函式可以用,但是卻不一定標準,例如aprintf。

我看了一下,後來則是用了vsnprintf,第一它可以限制住讓程式不會寫過頭造成SIGSEGV,

第二則是它回傳值是「他真正需要的長度」。

所以我就寫了一個這樣的程式碼,來對付超級長的字串。

int len = 256;

int retl = 0;

unsigned char* ptr = NULL;


do {

  if (ptr != NULL) {

    free(ptr);

    len = retl;

  }

  ptr = malloc(len);

  if (ptr) {

    memset(ptr, 0, len);

    ...

    retl = vsnprintf(ptr, len, ..., ...);

  }

/* if retl == len, the reuslt is still lack of the last char. */

} while (retl >= len);

...

free(ptr);

雖然當得我莫名奇妙的,但是解決的方法還算滿有意思的。

創作者介紹
創作者 荒廢的記事本 的頭像
jimmy899

荒廢的記事本

jimmy899 發表在 痞客邦 留言(0) 人氣( 2559 )