2012-07-14 56 views
3

我正在實現perror()等同於我正在使用的API。實現perror() - 問題

的PERROR()ISO C STD doc說:

的PERROR()函數不得改變標準 錯誤流的方向。

但以編程方式,它是什麼意思?我正在使用fprintf(stderr, ..)。使用它是一個錯誤嗎?如果屬實,爲什麼?如果在我的實現中出現了一些錯誤(請參閱下文),請爲我指出一些問題。基於我的解釋

查看我的C代碼:

void 
fooapi_perror(const char *s) 
{ 
    char *emsg; 

    if(s != NULL && *s != '\0') 
    fprintf(stderr, "%s: ", s); 

    emsg = fooapi_strerror(GetLastErrorCode()); 
    fprintf(stderr, "%s\n", emsg); 
    free(emsg); 
} 
+0

有趣的是,你的鏈接是POSIX標準,而不是ISO C標準。我的ISO/IEC 9899:1999副本與您鏈接的副本幾乎完全相同 - 除了您要查詢的行外! – cdarke 2012-07-14 15:38:53

+0

您可能希望將您的問題的標題從安靜的一般措辭'... perror() - issue'修改爲更具體的問題,比如'... perror():輸出流方向「,因爲它更多地涉及後者關於'perror()'實現本身。 – alk 2012-07-15 10:21:32

回答

9

每個C流具有屬性 - 「取向」任一「寬爲本」或「面向字節」,它是由第一操作確定在這個蒸汽上。當流不具有「方向」時,您可以更改蒸汽的方向。調用任何方向與流方向衝突的函數都會導致未定義的行爲。

例如,printf將使蒸汽成爲一個面向字節的面,而wprintf會導致蒸汽變爲寬面向。

就你的問題而言,錯誤不應改變其流的方向。

所以在你的代碼中,如果使用perror的流已經有了方向,你應該確保你沒有調用一個方向與流的當前方向衝突的函數。

3

您可以使用fwide(3)確定流的方向,然後使用它來決定是調用fprintf還是fwprintf

void 
fooapi_perror(const char *s) 
{ 
    const char *emsg = fooapi_strerror(fooapi_geterrcode()); 

    if (fwide(stderr, 0) <= 0) { 
     // byte-oriented or not yet oriented 
     if (s && *s) 
      fprintf(stderr, "%s: %s\n", s, emsg); 
     else 
      fprintf(stderr, "%s\n", emsg); 
    } else { 
     // wide-oriented 
     if (s && *s) 
      fwprintf(stderr, L"%s: %s\n", s, emsg); 
     else 
      fwprintf(stderr, L"%s\n", emsg); 
    } 

    free(emsg); 
} 

注:這不符合「不改變流方向」的要求時,流尚未收購的方向,因爲沒有辦法聯合國 -orient流,也不有什麼辦法可以將輸出發送到一個流而不必定向。 The GNU libc implementation of perror在這種情況下使用骯髒的黑客(複製底層文件描述符!)也許我們應該在「標準C寬字符支持並非真正適合用於任何目的」的情況下將它記下來,然後繼續前進。

切向kibitz:fooapi_strerror應該返回一個指向字符串常量的指針,而不是必須爲free的指針。