みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

C言語で半角スペースをデリミタとしたデータファイルを読み込むプログラム

C言語で半角スペースをデリミタとしたデータファイルを読み込むプログラムを作っています. まず, データのレコード数とフィールドの数をカウントしてその後, double型の2次元配列に必要なメモリ領域をmalloc関数にて確保して, 2次元配列にデータを代入していくという処理をやらせています.
とうプログラムをコンパイルして実行した所以下のようなエラーが出てどうやらFreeを2重にしてしまっていることがエラーログから分かるのですが, どこを修正していいかわかりません. どなたかお力を貸していただけないでしょうか?

■ソース■
#include<stdio.h>
#include<string.h>
#include<malloc.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");

____/*
____ 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);
______// then data have 2 pointer to double type

______for(j=0;j<fn;j++){
________data[j]=malloc(sizeof(double)*fn);
______}
____
____/*
____ insert data to array
____*/

____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(j=0;j<fn;j++){
________if(data[j]){
__________free(data[j]);
________}
______}
______free(data);
____}

__fclose(fp);
}

/*
int freeMem(){
}
*/

投稿日時 - 2010-08-02 21:21:22

QNo.6082541

すぐに回答ほしいです

質問者が選んだベストアンサー

for(j=0;j<fn;j++){
とその上の malloc とを比較してください.
そうそう, エラーメッセージは「Freeを2重にしてしまっている」とは言ってないよね.

投稿日時 - 2010-08-03 16:07:21

補足

>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

投稿日時 - 2010-08-03 16:32:32

ANo.5

このQ&Aは役に立ちましたか?

2人が「このQ&Aが役に立った」と投票しています

回答(6)

ANo.6

間違えて
for(j=0;j<fn;j++){
ってなってるところ, 実は 2か所あったのね.... かと思うとこれで正しいところもあったりするし, 少なくとも i と j については役割分担がうまくいってない.
あとは #3 の話. 最初の while でファイルを全部読んじゃってるから, 2つ目の while の前でファイルポインタを戻さないといけない.

投稿日時 - 2010-08-03 17:05:10

補足

>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(){
}
*/

投稿日時 - 2010-08-03 18:36:20

ANo.4

あと, 直接問題にはならないこともあるけど突っ込みどころ:
・fopen や malloc の返り値はちゃんと確認すべし
・英語がいろいろと怪しい
・関数の引数に配列を指定した意図はなんだろう

投稿日時 - 2010-08-03 12:04:19

補足

>fopen や malloc の返り値はちゃんと確認すべし
分りました.  
if(malloc(****)==NULL){
______printf("malloc failed!!\n");
______exit(1);
}
のようにしときます.

>英語がいろいろと怪しい
すみません. . .

>関数の引数に配列を指定した意図はなんだろう
特に深い意図はありません.
ファイル名を関数に渡したかっただけです.

投稿日時 - 2010-08-03 12:16:22

ANo.3

直接のエラーの原因は
> for(j=0;j<fn;j++){
なんだけど……

このプログラム、ファイルポインタを戻してないから、正常な値は表示しないよ。

投稿日時 - 2010-08-03 02:31:16

補足

>for(j=0;j<fn;j++){
の部分が原因の意味がわかりません. 教えていただけないでしょうか?

>このプログラム、ファイルポインタを戻してないから、正常な値は表示しないよ。

ファイルポインタを戻すとは, どういうことでしょうか?宜しければ教えていただけないでしょうか?

投稿日時 - 2010-08-03 12:18:53

ANo.2

ん, 少なくとも
for(j=0;j<fn;j++){
はおかしい.
ま, 「行によってデータの数が違う」場合にはやっぱり死ぬんだけど.

投稿日時 - 2010-08-02 23:38:31

補足

解答ありがとうございます.
>for(j=0;j<fn;j++){
>はおかしい.
の意味が分らないので教えていただけなでしょうか?

投稿日時 - 2010-08-03 12:12:03

ANo.1

>以下のようなエラー

どこにありますか?
また、差し支えがない範囲で、入力データの現物を見せていただくことは可能ですか?

投稿日時 - 2010-08-02 21:28:47

補足

エラーは, 字数の関係で掲載できませんでした. すみませんでした. データファイルは, 以下のようになっています. なお, 私の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

投稿日時 - 2010-08-02 23:45:43

あなたにオススメの質問