2012-07-14 59 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的指针。