4

私は次の行に沿っているCコードの一部を見ています

void printerror(char *message)
{
    printf ("There was an error: '%s'\n", message);
    switch (errno) {
       ... do stuff depending on errno
    }
}

printfは、関数に入ってからに到達するまでの間にerrnoを変更する可能性があるため、これは問題になる可能性があると思いますswitch。ただし、printfのマンページにはerrnoの設定については何も記載されていないので、設定されないと思いますか?どの関数がerrnoを使用するか使用しないかを保証する規格に何かありますか?

4

3 に答える 3

10

どの関数もerrnoを設定できますが、ゼロ以外の値に設定している場合に限ります。ANSI C仕様には、次のように記載されています。

errnoの値は、プログラムの起動時にゼロになりますが、ライブラリ関数によってゼロに設定されることはありません。* errnoを使用する場合、エラーの有無にかかわらず、ライブラリ関数呼び出しによってerrnoの値をゼロ以外に設定できます。標準の機能の説明には記載されていません。

*したがって、エラーチェックにerrnoを使用するプログラムは、ライブラリ関数呼び出しの前にerrnoをゼロに設定し、その後のライブラリ関数呼び出しの前にそれを検査する必要があります。

したがって、errnoを使用している場合のベストプラクティスのアプローチは、失敗する可能性のあるライブラリ呼び出しの直前に値を0に設定し、直後に読み取ることです。上記の場合、次のようなものを追加するだけで十分です。

int localErrno = errno

printfステートメントの直前で、スイッチにlocalErrnoを使用します。もちろん、これは、失敗した関数とprinterrorの呼び出しの間にライブラリ呼び出しがないことを前提としています。存在する場合は、呼び出しが失敗した後にerrnoを保存し、それをprinterror関数に渡す必要があります。

于 2010-12-08T19:01:09.997 に答える
4

まれに、printfがerrnoを設定できる場合があります。stdoutをプログラムからファイルにリダイレクトし、ファイルシステムがいっぱいになると、printf()は負の数を返し、errnoをENOSPC(デバイスにスペースが残っていない)に設定します。printf()を呼び出す前に、errnoのローカルコピーを作成する必要があります。

于 2010-12-08T20:23:34.573 に答える
3

C99標準では、次のように指定されています。

errnoの値は、プログラムの起動時にゼロになりますが、ライブラリ関数によってゼロに設定されることはありません。errnoの使用がこの国際規格の関数の説明に文書化されていない場合、エラーがあるかどうかに関係なく、ライブラリ関数呼び出しによってerrnoの値をゼロ以外に設定できます。

つまり、任意のライブラリ関数errnoで設定できます。それが実際に特定のケースにあるかどうかを判断するために、標準的な方法は、問題の関数を呼び出す前にゼロに設定することです。

于 2010-12-08T18:52:39.100 に答える