2012-03-27 7 views
0

私はfgetsからセグメンテーションを取得していますが、ときどきのみです。他の人のコードですが、私はmakefileを理解できませんので、printf文でデバッグしています...これをmain関数の2つの部分に置きます:(私は変数fと行を一度しか作成しませんが、 fopenのと両方の時間をファイルをfcloseは)私に二つの異なる出力を与えるsegfault on fgets ...時々

FILE *f = NULL; 
char line[1000]; 
if ((f=fopen(filename,"r+"))==NULL) 
{ 
    printf("Error opening file\n"); 
    f=0;//...handle error... //(usually just call abort() or return -1 
} 
//f = rfopen(fname, "r+"); 
printf("f from eval_args: %d, filename %s\n",f,filename); 
printf("trying to read from file...\n"); 
printf("%s\n",fgets(line, sizeof (line), f)); 
printf("...succeeded\n"); 
fclose(f); 

:。

f from eval_args: 4609600, filename /correct/path/to/file 
trying to read from file... 
100 

...succeeded 

f prior to entering density profile: 4609600, filename /correct/path/to/file 
trying to read from file... 
Segmentation fault (core dumped) 

私は '内の収まらないファイルが正しく開かれ、複数の文字を読ん防ぐされていることを確認してくださいライン'。私は1つのフォーラムで、ファイル名が49文字を超えてはならないことを知りました...しかし、a)それは奇妙な制限であり、b)なぜ最初に動作するのですか?

他に何が確認できるか知っていますか?

+0

ないのprintf()印刷 '(ヌル)' NULL文字列に遭遇するとしていますか? –

+0

問題を再現する小さなコンパイル可能なプログラムを投稿できますか? – hmjd

+0

まず、 'fgets'を別の文として置いてください。デバッガを使って、エラーを探して調べるのを助けてください。 –

答えて

0

あなたの説明から、おそらく2番目のfgetsが成功しない可能性があるため、NULLが返され、セグメントの障害が発生しました。そして、なぜ2番目のfgetsが失敗するのですか?あなたは

fgets仕様を参照して...それを見てみることがあります。成功した

、機能は同じstrのパラメータを返します。 ファイルの終わりに遭遇し、文字が読み込まれていない場合、strの内容は変更されず、NULLポインタが返されます。 エラーが発生した場合は、NULLポインタが返されます。 ferrorまたはfeofのいずれかを使用して、エラーが発生したか、ファイルの終わりに達したかどうかを確認します。 http://www.cplusplus.com/reference/clibrary/cstdio/fgets/

だから、一般的には直接fgetsの戻り値を使用することをお勧めではありません。

+0

チップをありがとう、私は別の行に今fgetsとprintfの呼び出しを入れて、それはまったく返すことはありませんfgets関数のようです。 – craq

+0

@craq - 'fgets'呼び出しの前にあなたのファイルハンドルを誤って閉じたり上書きしたりしていないことを確認してください。 –

+0

@ジョン - 故意にそれを閉じて、それを上書きして再び開くのは大丈夫でしょうか? – craq

1

面倒なことではないかもしれませんが、あなたが知っていると思います。

ビットを美化することでしたが、

#include <stdio.h> 
#include <stdarg.h> 

#define MAX_LINE 1024 

void dbg_fprnt(FILE *fh, char *fmt, ...) 
{ 
    char buf[MAX_LINE]; 
    char inf[MAX_LINE] = {0}; 
    va_list args; 

    if (fmt && *fmt) { 
     va_start(args, fmt); 
     va_end(args); 
     vsprintf(inf, fmt, args); 
    } 

    buf[0] = '\n'; 
    buf[1] = '\0'; 
    if (ferror(fh)) { 
     fprintf(stderr, " * ERR, ferror() --- \n"); 
    } else if (fh == NULL) { 
     fprintf(stderr, 
      " * DBG PRNT ERR;; Trying to print from NULL ---\n"); 
    /* else if (and so forth) */ 
    } else { 
     if (fgets(buf, MAX_LINE, fh) == NULL) { 
      perror(" * ERR DBG PRNTF FGETS, --"); 
     } 
    } 
    printf("%-15s FC:: %s", inf, buf); 
} 

int main(void) 
{ 
    char *fn = "lorem_ipsum"; 
    FILE *fh; 

    if ((fh = fopen(fn, "r")) == NULL) { 
     fprintf(stderr, 
      "Unable to open '%s' for read.\n", 
      fn); 
     return 1; 
    } 

    setbuf(stdout, NULL); 

    dbg_fprnt(fh, "SOME LINE: %d", 123); 
    dbg_fprnt(fh, "%s", "SASA"); 
    dbg_fprnt(fh, ""); 
    dbg_fprnt(fh, NULL); 
    dbg_fprnt(fh, "%s %d !", "Woot", 33); 
    dbg_fprnt(fh, "@%d :::", __LINE__); 
    fclose(fh); 
    dbg_fprnt(fh, "@%d :::", __LINE__); 


    return 0; 
} 

出力例:お使いのプリントアウトから

./fe 
SOME LINE: 123 FC:: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 
SASA   FC:: tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, 
       FC:: quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo 
       FC:: consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse 
Woot 33 !  FC:: cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non 
@52 :::   FC:: proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 
* ERR DBG PRNTF FGETS, --: Bad file descriptor 
@54 :::   FC:: 
+0

うわー、そのおかげで、私は少しを学んだ。私はあなたに少し異なる出力を得るが、それはおそらく重要ではない。特にfgetsには当てはまりません。私の場合、出力の最後の3行は次のようになります: '@ 62 ::: FC :: proident、culpa qui officia des molunt anim id est laborum.'にあります。 ' * ERR DBG PRNTF FGETS、 - :不正なファイル'' '@ 64 ::: FC ::' – craq

+0

@craq: '__LINE__'、' __FILE__'などはプリプロセッサマクロで、_your_ファイルのlinenumberなどを出力します。ですから、_my_ファイルでは、fclose(fh)の前の "dbg_fprnt(fh" @%d ::: "、__LINE __);' "は52行目にあり、_your_ファイルでは62行目にあります。 – Morpfh

0

f from eval_args: 4609600, filename /correct/path/to/file 
trying to read from file... 
100 

...succeeded 

f prior to entering density profile: 4609600, filename /correct/path/to/file 
trying to read from file... 
Segmentation fault (core dumped) 

あなたが持っている「Fに入る前に"f from eval_args"ではなく "density profile"に変更するが、 "density proあなたの提供するソースに「ファイル」が存在しない場合は、同じコードを実行していないと思います。

と "//...handle error ... //(通常は単にabort()を呼び出すか-1を返す"というコードでは処理するコードがないので、まだダウンしてコアダンプすることができます。正常終了

ストリームは、ストリームのファイル終了標識が設定されなければならない、ファイルの終わりにある場合、関数fgets()は、Sを返すは:関数fgetsからの戻りの説明から

。 fgets()はヌルポインタを返す。読み取りエラーが発生した場合は、ストリームのエラーインジケータを設定し、fgets()はNULLポインタを返し、errnoにエラーを示す値を設定します。

したがって、EOFなどの悪いことがあれば、そのprintfコアダンプが作成されます。

が、私はの線に沿って何かをお勧め:

FILE *f = fopen(filename,"r+"); 
    if (f) { 
     char line[1000]; 
     printf("f from eval_args: %p, filename %s\n",f,filename); 
     printf("trying to read from file...\n"); 
     while(fgets(line, sizeof (line), f)) printf("%s",line); 
     fclose(f); 
    } 
    else printf("Error opening file\n"); 
+0

はい、私は出力がどこから来たのかを簡単に知ることができました。そして、そうですね、エラーを処理しないのは怠惰ですが、そういう場合は少なくともprintfステートメントのために知っていました。繰り返すが、それはfgets呼び出しであり、segfaultを生成するprintfではない。私は今、 'char * dummy;を持っています。 dummy = fgets(行、sizeof(行)-1、f); printf( "fgetsが返されました\ n"); ...と 'segfaultはその行を印刷する前に発生します。 – craq