2012-02-22 23 views
1

は、私はこのようなファイルから読み込まいます:なぜfreadが "Bad file descriptor"に遭遇するのですか?

#include <stdio.h> 

int main() { 
    FILE *fp = fopen("sorted_hits", "r+"); 

    while(!feof(fp)) { 
     int item_read; 
     int *buffer = (int *)malloc(sizeof(int)); 
     item_read = fread(buffer, sizeof(int), 1, fp); 
     if(item_read == 0) { 
      printf("at file %ld\n", ftell(fp)); 
      perror("read error:"); 
     } 
    } 
} 

このファイルは大きいと私は時々、「不正なファイルディスクリプタ」エラーを得ました。 「ftell」は、エラーが発生したときにファイルの位置が停止したことを示します。

なぜ「時々」であるのか分かりませんが、それは普通ですか?問題は私のコードや私のハードディスクにありますか?これをどう扱う?

答えて

5

perrorプリントを(非翻訳)バイナリモードでファイルを開きます。 errnoは、システムコールにエラーが返ったときは常にエラーコードに設定されます。しかし、システムコールが失敗しない場合は、errnoは変更されず、以前に含まれていたものが含まれ続けます。今度はfreadが0を返した場合は、エラーがあったか、ファイルの最後に達したことを意味します。後者の場合、errnoは設定されておらず、以前からランダムなゴミが含まれている可能性があります。

この場合、おそらくエラーが表示されていないことを意味する「ファイル記述子の不良」というメッセージが表示されます。エラーが発生したかどうかを調べるには、ferror(fp)をチェックする必要があります。

+0

+1 nice catch .. –

+0

それに加えて、 'printf("ファイル%ld \ n "、ftell(fp));' 'perror "") 'はerrnoを設定することができるので、印刷されるfreadのerrnoではないかもしれません。 – nos

1

ファイルを読むときに、テキストモードとバイナリモードが混在しているようです。

通常、freadを使用すると、バイナリファイルから読み込みます。つまり、freadはバッファサイズに一致するバイト数を読み取りますが、テキストモード(r +)でファイルを開いているようです。 ftell改行は他の文字とは異なって扱われるため、テキストモードで開いたファイルでは正しく動作しません。

ではなく説明的な文字列としてerrnoにあるどんな

FILE *fp = fopen("sorted_hits", "rb+"); 
+0

これは実際に私の問題でした。私のファイルはモード "r"でオープンされ、nealryはすべてファイル化されましたが、いくつかの特殊文字(私は正確にはわからない)がファイル内にあるとき、readコマンドは "bad file descriptor"というエラーで失敗します。だからヒントのおかげで、それは私の問題を修正! –

+0

@MeisterSchnitzel私が助けることができたことを嬉しく思います。 –

0

ループが本当に見える場合、私の推測によれば、あなたのループはそれほどひどくリークしているので、あなたのプロセスはちょうどメモリが足りなくなっているので多かれ少なかれ偽のエラーになるでしょう。(mallocあなたのループの繰り返しですが、freeと一致する呼び出しはありません)。

while (!feof(fp))の(一般的ではありますがほとんど常に間違っている)使用から少し問題に遭遇している可能性もあります。

printfは、変換とタイプが一致していないため、未定義の動作もします(しかし、多くの現在のシステムでは、longとintが同じサイズであるため関係がありません)。

これらの問題を修正することで、観察した問題は削除される場合もあれば、削除されない場合もありますが、少なくとも表示されている場合は、問題の原因を絞り込むことができます。

int main() { 
    FILE *fp = fopen("sorted_hits", "r+"); 

    int buffer; 

    while(0 != fread(&buffer, sizeof(int), 1, fp)) 
     ; // read file but ignore contents. 

    if (ferror(fp)) { 
     printf("At file: %ld\n", ftell(fp)); 
     perror("read error: "); 
    } 
} 
関連する問題