实现perror() - 问题

时间:2012-07-14 15:25:01

标签: c posix

我正在实现与我正在使用的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);
}

2 个答案:

答案 0 :(得分:9)

每个C流都有一个属性 - “方向”或者“面向宽”或“面向字节”,这是由对此蒸汽的第一次操作决定的。当流没有“方向”时,可以改变蒸汽的方向。调用方向与流方向冲突的任何函数都会导致未定义的行为。

例如,printf会使蒸汽成为面向字节的,而wprintf会使蒸汽变为宽广的。

就你的问题而言,perror不应改变其流的方向。

所以在你的代码中,如果perror使用的流已经有了一个方向,你应该确保你没有调用一个方向与流的当前方向冲突的函数。

答案 1 :(得分: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);
}

注意:当流尚未获取方向时,这不符合“不改变流方向”的要求,因为无法 un -orient流,也没有任何方法可以将输出发送到流而不给它一个方向。 The GNU libc implementation of perror在这种情况下采用脏兮兮的方法(复制底层文件描述符!)也许我们应该在“标准C宽字符支持并不是真正适合目的”之前将其白垩起来并继续前进。

切向kibitz:fooapi_strerror应该返回一个指向字符串常量的指针,而不是一个必须为free d的指针。