3

perror()使用している API と同等のものを実装しています。

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);
}
4

2 に答える 2

9

各 C ストリームにはプロパティがあります。「方向」は、このストリームの最初の操作によって決定される「ワイド指向」または「バイト指向」です。ストリームに「向き」がない場合、ストリームの向きを変更できます。向きがストリームの向きと競合する関数を呼び出すと、未定義の動作が発生します。

たとえば、printf ではストリームがバイト指向になり、wprintf ではストリームがワイド指向になります。

あなたの質問に関する限り、perror はそのストリームの向きを変更すべきではありません。

そのため、コード内で、perror が使用しているストリームに既に方向がある場合、方向がストリームの現在の方向と競合する関数を呼び出していないことを確認する必要があります。

于 2012-07-14T16:15:38.077 に答える
3

でストリームの方向を決定し、それを使用してまたはfwide(3)を呼び出すかどうかを決定できます。fprintffwprintf

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);
}

注: ストリームがまだ向きを取得していない場合、これは「ストリームの向きを変更しない」という要件に準拠しませ。向きを指定せずにストリーミングします。 この場合、 GNU libc の実装はperror汚いハックに頼ります (基礎となるファイル記述子を複製します!) おそらく、「標準の C ワイド文字サポートはとにかく目的に合わない」という下に書き留めて、先に進むべきです。

タンジェンシャル キビッツ:fooapi_strerror文字列定数へのポインターを返す必要がありますfree。d にする必要があるポインターではありません。

于 2012-07-14T17:23:38.423 に答える