- ベストアンサー
C言語で半角スペースをデリミタとしたデータファイルを読み込むプログラム
- C言語で半角スペースをデリミタとしたデータファイルを読み込むプログラムを作成中です。
- データのレコード数とフィールドの数をカウントし、2次元配列にデータを代入する処理を実装しています。
- プログラムをコンパイルして実行した結果、2重のFreeエラーが発生しました。修正方法を教えてください。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
for(j=0;j<fn;j++){ とその上の malloc とを比較してください. そうそう, エラーメッセージは「Freeを2重にしてしまっている」とは言ってないよね.
その他の回答 (5)
- Tacosan
- ベストアンサー率23% (3656/15482)
間違えて for(j=0;j<fn;j++){ ってなってるところ, 実は 2か所あったのね.... かと思うとこれで正しいところもあったりするし, 少なくとも i と j については役割分担がうまくいってない. あとは #3 の話. 最初の while でファイルを全部読んじゃってるから, 2つ目の while の前でファイルポインタを戻さないといけない.
補足
>i と j については役割分担がうまくいってない. iは行をjはフィールド方向という風に整理してみました. >while でファイルを全部読んじゃってるから, 2つ目の while の前でファイルポインタを戻さないといけない. 確かにそうですね…fseekでファイルポインタ戻さないといけないです. ■修正後■ #include<stdio.h> #include<string.h> #include<malloc.h> #include<stdlib.h> #define LINE_MAX_SIZE 5120 int main(void){ _road("test.dat"); } int road(char fname[100]){ _FILE *fp; _char line[LINE_MAX_SIZE]; _char *tp; _char *token=" "; _int rn=0; _int fn; _int i=0; _int j=0; _ _fp=fopen(fname,"r"); _if(fp==NULL){ __fprintf(stderr,"%s : No such file or directory!!\n",fname); _} __/* __ check record number and field number __*/ __while(fgets(line,sizeof(line),fp)){ ___ ___tp=strtok(line,token); ___fn=0; ___while(tp!=NULL){ ____tp=strtok(NULL,token); ____fn++; ___} ___rn++; __} __//printf("rn=%d fn=%d\n",rn,fn); __/* ___make 2 dimension array dynamically __*/ ___double **data; ___ ___data=malloc(sizeof(double *)*rn); ___if(data==NULL){ ____fprintf(stderr,"Failed fetch memory\n"); ____exit(1); ___} ___// then data have 2 pointer to double type ___for(i=0;i<rn;i++){ ____data[i]=malloc(sizeof(double)*fn); ____if(data[i]==NULL){ _____fprintf(stderr,"Failed fetch memory\n"); _____exit(1); ____} ___} __ __/* __ insert data to array __*/ __// move file pointer to file haed __fseek(fp,0L,SEEK_SET); __i=j=0; __while(fgets(line,sizeof(line),fp)){ ___j=0; ___tp=strtok(line,token); ___data[i][j]=atof(tp); ___while(tp!=NULL){ ____j++; ____tp=strtok(NULL,token); ____data[i][j]=atof(tp); ___} ___i++; __} __for(i=0;i<rn;i++){ ___for(j=0;j<fn;j++){ ____printf("%f ",data[i][j]); ___} ___printf("\n"); __} __/* __/ free memory for data[][] __*/ __if(data){ ___for(i=0;i<rn;i++){ ____if(data[i]){ _____free(data[i]); ____} ___} ___free(data); __} _fclose(fp); } /* int freeMem(){ } */
- Tacosan
- ベストアンサー率23% (3656/15482)
あと, 直接問題にはならないこともあるけど突っ込みどころ: ・fopen や malloc の返り値はちゃんと確認すべし ・英語がいろいろと怪しい ・関数の引数に配列を指定した意図はなんだろう
補足
>fopen や malloc の返り値はちゃんと確認すべし 分りました. if(malloc(****)==NULL){ ______printf("malloc failed!!\n"); ______exit(1); } のようにしときます. >英語がいろいろと怪しい すみません. . . >関数の引数に配列を指定した意図はなんだろう 特に深い意図はありません. ファイル名を関数に渡したかっただけです.
- magicalpass
- ベストアンサー率58% (378/648)
直接のエラーの原因は > for(j=0;j<fn;j++){ なんだけど…… このプログラム、ファイルポインタを戻してないから、正常な値は表示しないよ。
補足
>for(j=0;j<fn;j++){ の部分が原因の意味がわかりません. 教えていただけないでしょうか? >このプログラム、ファイルポインタを戻してないから、正常な値は表示しないよ。 ファイルポインタを戻すとは, どういうことでしょうか?宜しければ教えていただけないでしょうか?
- Tacosan
- ベストアンサー率23% (3656/15482)
ん, 少なくとも for(j=0;j<fn;j++){ はおかしい. ま, 「行によってデータの数が違う」場合にはやっぱり死ぬんだけど.
補足
解答ありがとうございます. >for(j=0;j<fn;j++){ >はおかしい. の意味が分らないので教えていただけなでしょうか?
- asuncion
- ベストアンサー率33% (2127/6289)
>以下のようなエラー どこにありますか? また、差し支えがない範囲で、入力データの現物を見せていただくことは可能ですか?
補足
エラーは, 字数の関係で掲載できませんでした. すみませんでした. データファイルは, 以下のようになっています. なお, 私のPC環境は, ubuntu10.04でadm64. コンパイラはgcc(4.4.3)です. ■データファイル■ 12.03 3.25 3.59 2.03 5.36 4.52 0.23 3.40 4.69 8.69 1.23 5.40 ■エラー■ 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 *** glibc detected *** ./a.out: double free or corruption (out): 0x000000000130b270 *** ======= Backtrace: ========= /lib/libc.so.6(+0x775b6)[0x7f8b00c7a5b6] /lib/libc.so.6(cfree+0x73)[0x7f8b00c80e53] ./a.out[0x400b57] ./a.out[0x400807] /lib/libc.so.6(__libc_start_main+0xfd)[0x7f8b00c21c4d] ./a.out[0x400739] ======= Memory map: ======== 00400000-00401000 r-xp 00000000 08:01 7210411 /home/hoge/prog/roadData_c/a.out 00600000-00601000 r--p 00000000 08:01 7210411 /home/hoge/prog/roadData_c/a.out 00601000-00602000 rw-p 00001000 08:01 7210411 /home/hoge/prog/roadData_c/a.out 0130b000-0132c000 rw-p 00000000 00:00 0 [heap] 7f8afc000000-7f8afc021000 rw-p 00000000 00:00 0 7f8afc021000-7f8b00000000 ---p 00000000 00:00 0 7f8b009ec000-7f8b00a02000 r-xp 00000000 08:01 9437263 /lib/libgcc_s.so.1 7f8b00a02000-7f8b00c01000 ---p 00016000 08:01 9437263 /lib/libgcc_s.so.1 7f8b00c01000-7f8b00c02000 r--p 00015000 08:01 9437263 /lib/libgcc_s.so.1 7f8b00c02000-7f8b00c03000 rw-p 00016000 08:01 9437263 /lib/libgcc_s.so.1 7f8b00c03000-7f8b00d7d000 r-xp 00000000 08:01 9437484 /lib/libc-2.11.1.so 7f8b00d7d000-7f8b00f7c000 ---p 0017a000 08:01 9437484 /lib/libc-2.11.1.so 7f8b00f7c000-7f8b00f80000 r--p 00179000 08:01 9437484 /lib/libc-2.11.1.so 7f8b00f80000-7f8b00f81000 rw-p 0017d000 08:01 9437484 /lib/libc-2.11.1.so 7f8b00f81000-7f8b00f86000 rw-p 00000000 00:00 0 7f8b00f86000-7f8b00fa6000 r-xp 00000000 08:01 9437267 /lib
補足
>data=malloc(sizeof(double *)*rn); でrn個のポインタのためのメモリ領域を確保しているにもかかわらず forでfn個まわしてしまったいるのですね… 正しくは for(j=0;j<rn;j++){ ですね. さっそく修正してコンパイル実行した所. 以下のような結果になり値が正しく表示されませんでした. ■結果■ 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 Segmentation fault