0

私にとって不可解な何かを理解するのに役立つことができました。ファイルを読み込む fopen() の位置に関するものです。

次のコード (gcc 4.5.2 でコンパイルされた C):

#include <stdlib.h>
#include <stdio.h>

void try_fopen(FILE* f_handle, const char* f_name, const char* mode) {
    f_handle = fopen(f_name, mode);
    if( f_handle == NULL ) {
        fprintf(stderr, "Error: Unable to open '%s'.", f_name);
        exit(EXIT_FAILURE);
    }
}

int cnt_ones(FILE* pFile) {
    int c;
    int n = 0;

    do {
      c = fgetc (pFile);
      if (c == '1') n++;
    } while (c != EOF);

    return n;
}

fopen を関数に入れると Segfault が発生するのはなぜですか。

int main (int argc, char** argv) {
    FILE * pFile;
    try_fopen(pFile, argv[1], "r"); // Gives a Segfault

    printf ("The file contains %d ones.\n", cnt_ones(pFile) );
    fclose (pFile);

    return 0;
}

それをメインに入れながら(そうでない場合と一緒に):

int main (int argc, char** argv) {
    FILE * pFile;
    pFile = fopen(argv[1], "r"); // While this doesn't give a Segfault
    if( pFile == NULL ) {
        fprintf(stderr, "Error: Unable to open '%s'.", argv[1]);
        exit(EXIT_FAILURE);
    }

    printf ("The file contains %d sign characters.\n", cnt_ones(pFile) );
    fclose (pFile);

    return 0;
}
4

4 に答える 4

4

C は参照渡しではなく値渡しであるため、ポインターを に渡す必要がありますpFile。それ以外の場合は、関数スコープ外で変更しないでください。

void try_fopen(FILE** f_handle, const char* f_name, const char* mode) {
    *f_handle = fopen(f_name, mode);
    if( *f_handle == NULL ) {
        fprintf(stderr, "Error: Unable to open '%s'.", f_name);
        exit(EXIT_FAILURE);
    }
}

// ...
try_fopen(&pFile, argv[1], "r");
于 2012-05-14T08:50:42.087 に答える
1

ポインタpFileは値によって関数に渡されるためtry_openです。関数内で変更された値は、 では使用できませんmain。これを解決するには、ポインターのアドレスを関数に渡す必要があるため、 toの結果をtry_open受け入れFILE**て代入します。この関数を呼び出すときは、usingのアドレスを渡す必要があります。fopen*pFilepFile&pFile

于 2012-05-14T08:50:57.607 に答える
1

次のいずれかを実行できます。

File * fp;
try_fopen( &fp,.....); /* void try_fopen (FILE ** fp,....) */

または以下:

File * fp = try_fopen("file name"); /* FILE * try_fopen (const char * file_name,...) */
于 2012-05-14T09:02:09.670 に答える
0

理由は単純です。関数に FILE* を渡すと、Value によって渡されるため、更新が失われます。関数に FILE ** を渡してみてください。機能します。コード スニペットについては、上記の Binyamin Sharet の回答を参照してください。

この理由は、このリンクを読むことで理解できます

または

関数 try_open を変更して、戻り値として FILE * を返すことができます。

FILE *try_fopen(const char* f_name, const char* mode) 
{ 
   FILE *f_handle = NULL;    
  *f_handle = fopen(f_name, mode);     
   if( *f_handle == NULL ) 
   {         
     fprintf(stderr, "Error: Unable to open '%s'.", f_name);         
     exit(0);     
   } 
} 

  //In the main function.
  FILE *pFile = try_fopen(argv[1], "r");
于 2012-05-14T08:51:42.277 に答える