web-dev-qa-db-ja.com

C fopenは、errnoが2の書き込みで失敗します

これが2のerrnoで失敗しているように見える理由がわかりません。

char debugText [256];
sprintf (debugText, "C:\\List.txt");
dfile = fopen( debugText, "w");
fprintf ( dfile, "  err %d \n", errno);

DfileがNULLのときにファイルが作成され、出力がいっぱいになるためと思われます。

では、何が起こっているのでしょうか。

6
JPM

これはすべて、errnofopen呼び出しの後に値2を持っていたことを示しています。 dfile == NULLかどうかを確認しなかったため、呼び出しが失敗したことはわかりません。出力が実際にファイルに書き込まれた場合は、おそらくfopen呼び出しが成功し、errno値が以前の呼び出しから残っていたため、明示的に行っていない可能性があります。

失敗した呼び出しはerrnoをゼロ以外の値に設定できますが、成功した呼び出ししないerrnoを0に設定します。エラーをチェックするには、次のことを行う必要があります。

  • 呼び出しの前にerrnoを0に設定します。
  • 呼び出しを行い、返された値をチェックして、成功したか失敗したかを確認します。そして
  • 呼び出し後にerrnoの値を確認しますが、失敗したことがわかっている場合はのみです(そうでない場合、errnoの値は無意味です)。

defile == NULLの場合、fprintf呼び出しの動作は未定義です。おそらく失敗するでしょう。

一方、dfileNULLであると言います。どうやってわかったの?あなたのコードはそれをチェックしません。 (fopen呼び出しが実際に失敗した場合、C:\List.txtの内容は、プログラムの前回の実行から残っている可能性がありますか?)

このプログラムからどのような出力が得られますか?

#include <stdio.h>
#include <errno.h>
int main(void) {
    char debugText [256];
    FILE *dfile;

    sprintf (debugText, "C:\\List.txt");
    dfile = fopen( debugText, "w");
    if (dfile == NULL) {
        printf("fopen failed, errno = %d\n", errno);
    }
    else {
        printf("fopen succeeded\n");
    }
    return 0;
}
9
Keith Thompson
_2 ENOENT No such file or directory.  A component of a specified pathname
         did not exist, or the pathname was an empty string.
_

エラーコードのリストは次のとおりです。

http://www.thegeekstuff.com/2010/10/linux-error-codes/

ただし、NULLのこの値が他の値から残っている可能性があるため、最初にfopen()errnoを返したかどうかを確認する必要があります。

5
Johnny Mnemonic

errnoをゼロに設定するライブラリ関数はありません。

関数がエラーを報告した後でのみ、errnoをチェックする必要があります。

たとえば、コードは次のようになります。

if ((dfile = fopen(debugText, "w")) == 0)
    ...then fopen() failed and errno is relevant...

関数が失敗を報告しない場合、errnoの値は何でもかまいません。たとえば、Solarisでは、errnoが端末に接続されていないため、操作が成功した後、ENOTTYstdoutに設定されることがよくあります。実際に何かがうまくいかなかったという意味ではありません。これは、標準出力が端末であるかどうかのテストが失敗したことを意味します(端末ではないため)。

3