• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:C言語のデバック 領域の二重解放が原因か??)

C言語のデバック 領域の二重解放が原因か??

このQ&Aのポイント
  • C言語でのデバック時にglibc detectedというエラーが出る。領域の二重解放が原因かどうかわからない。
  • 流体力学の研究でフリーの数値解析ソフトを使っているが、ポスト処理の機能が弱いため、C言語で自作している。
  • 翼周りの圧力分布を計算し、ある点の圧力の時間変化を知りたいため、プログラムを作成した。しかし、glibc detectedエラーが出る。

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

  • ベストアンサー
  • a_kwn
  • ベストアンサー率34% (8/23)
回答No.5

/* ベクトルの領域確保 */ x = dvector(1,n); /* x[1...n] */ ここのコメントと、dvector の関数の実装は一致しています。 でも、 for( i = 0 ; i <= n ; i++) {  … input_vector2( x, t, i,fin, fout ); /* ベクトルxの入出力 */  … } と、iが0からnまで動くのに input_vector2関数内で、 void input_vector2( double *b, double t,int i ,FILE *fin, FILE *fout) {  …  fscanf(fin, "%lf", &b[i]);  … } と x[0...n] に対して代入が行われることになるのは、どうなのでしょうか?

ryutaitaro
質問者

お礼

その通りでした。 要素の始めが1からになるように設定しているのに、0から代入している点に間違いがあったようです。 ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (4)

  • a_kwn
  • ベストアンサー率34% (8/23)
回答No.4

char fn[5];/*圧力を指定するためのパス*/ … sprintf( fn,"./%5.4f/p",t); まずは、fn のバッファの長さを適切にしてみては? (最後のnull文字分も忘れずに!)

ryutaitaro
質問者

お礼

解答ありがとうございます。 明らかにおかしいですね。 fn[11]にすれば問題ないですよね?

全文を見る
すると、全ての回答が全文表示されます。
  • wormhole
  • ベストアンサー率28% (1619/5653)
回答No.3

>>なぜそこが二重解放になるのでしょうか? > >そのようなケースがありえるのかわかりませんが >nl1 が 0 のときには起こりえそうですよ。 すいません。勘違いでした。 なりませんね。 Valgrindで調べてみてはいかがでしょうか。

ryutaitaro
質問者

お礼

何度もありがとうございます。 私自身もfree_dmatrixなどはあまり分からずに使っているのですが、同じものを何度か使っていままでエラーがなかったのでたぶん問題はないだろうと思います。 既存の問題のないプログラムから変更した箇所はメイン関数の部分とinput_vectorだけなのでそのあたりのどこかがおかしいのだと思うんですが、わからないです。 Vargrindというデバックツール(?)があるんですね。 導入が私には難しそうなので、どうしようもなかったら使ってみようと思います。 ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。
  • wormhole
  • ベストアンサー率28% (1619/5653)
回答No.2

>なぜそこが二重解放になるのでしょうか? そのようなケースがありえるのかわかりませんが nl1 が 0 のときには起こりえそうですよ。 余計なお世話なんでしょうが dmatrix, free_dmatrix は、無駄に難しい気がするので リファクタリングした方がいいと思います。

全文を見る
すると、全ての回答が全文表示されます。
  • tda410
  • ベストアンサー率40% (2/5)
回答No.1

>実行ディレクトリ内には各時刻(以下のプログラム内では t)のディレクトリが存在し、その中に圧力(p)のデータが存在しています。 不具合が発生する状況が確認できないので、よくわかりません。 質問する場合は、問題が再現する状態をすべて提示してください。 とりあえずコードを見ましたが free_dmatrixの /* メモリの解放 */ for ( i = nr1 ; i <= nr2 ; i++) free((void *)(a[i]+nl1)); free((void *)(a+nr1)); ←ここ って二重解放になりそうですよ。

ryutaitaro
質問者

お礼

素早い解答どうもありがとうございます。 「問題が再現する状態」とは何なのかよくわからないですが、 「実行ディレクトリ内には各時刻(以下のプログラム内では t)のディレクトリが存在し、その中に圧力(p)のデータが存在しています。」の一文がよくわからなかったということですか?これなら大丈夫ですか?舌足らずですいません。 「プログラムを実行するディレクトリ内には各時刻(0.0001~0.0004 プログラム中では変数tで表しています)のディレクトリが存在し、その中に圧力(p)のデータが存在しています。」 なぜそこが二重解放になるのでしょうか?

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • Xcodeでのc言語のプログクムについて。

    Xcodeでのc言語のプログクムについて。 ルンゲークッタ法のプログラムを書いているのですがビルドエラーになってしまい、原因が分かりません。  ビルド結果は、 "_func",referenced from: _main in main.o "_dvector",referenced from: _main in main.o _rk4 in main.o symbol(s) not found collect2: ld returned 1 exit status  プログラムは、 #include <stdio.h> #include <stdlib.h> double *dvector(long i, long j); /* ベクトル量領域の確保*/ void free_dvector(double *a, long i); /* 領域の解放*/ double func(double x, double y); /* 関数の定義 */ /* ルンゲークッタ法 */ double *rk4( double y0, double a, double b, int n, double (*f)()); int main (void) { double *y, h, a=0.0, b=1.0, y0=1.0 ; int i, n; printf("分割式を入力してください-->"); scanf("%d",&n); y = dvector( 0, n ); /*領域の確保*/ y = rk4( y0, a, b, n, func ); /*ルンゲクッタ法*/ /* 結果の表示 */ h = (b-a)/n ; /* 刻み幅 */ for (i = 0 ; i <= n ; i++) { printf("x=%f \t y=%f \n", a+i*h, y[i] ); } return 0; } /* ルンゲクッタ法 */ double *rk4( double y0, double a, double b, int n, double (*f)() ) { double k1, k2, k3, k4, h, *y, x; int i; y = dvector( 0, n ); /* y[0,1,....,n]の確保 */ h = (b-a)/n ; /* 初期値の設定 */ y[0] = y0; x = a; /* ルンゲクッタ法 */ for ( i = 0 ; i < n ; i++) { k1 = f(x,y[i]); k2 = f(x+h/2.0, y[i]+h*k1/2.0); k3 = f(x+h/2.0, y[i]+h*k2/2.0); k4 = f(x+h, y[i]+h*k3); y[i+1] = y[i] + h/6.0 * ( k1 + 2.0*k2 + 2.0*k3 + k4 ); x += y[i]; } return y; free_dvector(y, 0); /* 領域の解放 */ }

  • ガウスの消去法:C言語

    連立方程式をガウスの消去法を用いて解くプログラミングをVisual Studioで作成したいのですが、ビルドがうまくいきません ビルドをすると、 ・リンケージ指定子がグローバル スコープで宣言されていません ・直前のエラーを修復できません。コンパイルを中止します。 と表示されデバックできません。 どなたかご教授願います。 ちなみに、C++ win32コンソールアプリケーションを使用しています。 ソースコード↓ #include "stdafx.h" int _tmain(int argc, _TCHAR* argv[]) { #include <stdio.h> #include <math.h> #define EPS 1.0e-5 #define N 10 void DATAIN(char name[], int nr, int nc, double ma[]); void RESULT(char name[], int nr, int nc, double ma[]); int PIVOT(int *num, int nr, int k, double ma[]); int GAUSS(int nr, double ma[], double mb[], double mx[]); int main(void) { int nr,nc; int flag; double ma[N*N],mb[N],mx[N]; printf("方程式の数 nr="); scanf("%d",&nr); nc=nr; printf("\n配列maのデータ%d*%d=%d",nr,nr,nr*nr); printf("個を入力"); DATAIN("ma",nr,nc,ma); printf("\n配列mbのデータ %d 個を",nr); printf("入力してください"); DATAIN("mb",nr,1,mb); flag=GAUSS(nr,ma,mb,mx); if(flag) printf("計算不能"); else RESULT("mx",nr,1,mx); return (0); } void DATAIN(char name[], int nr, int nc, double ma[]) { int i,j; printf("\n---入力データ---\n"); for(i=0; i<nr; i++) { for(j=0; j<nc; j++) { printf(" %s[%d%d] = ",name,i+1,j+1); scanf("%lf",&ma[nc*i+j]); } } } void RESULT(char name[], int nr, int nc, double ma[]) { int i,j; printf("\n---計算結果---\n"); for(i=0; i<nr; i++) { for(j=0; j<nc; j++) printf(" %s[%d] = %8.5lf",name,i+1,ma[nc*i+j]); printf("\n"); } } int PIVOT(int *num, int nr, int k, double ma[]) { int i; double aa,bb; *num=k; aa=fabs(ma[nr*k+k]); for(i=k+1; i<nr; i++) { if (fabs(ma[nr*i+k])>aa) { *num=i; aa=fabs(ma[nr*i+k]); } } if(fabs(aa)<=EPS) return (1); if(*num==k) return (0); for(i=k; i<nr; i++) { bb=ma[nr*k+i]; ma[nr*k+i]=ma[nr*(*num)+i]; ma[nr*(*num)+i]=bb; } return (0); } int GAUSS(int nr, double ma[], double mb[], double mx[]) { int i,j,k; int num; double cc; for(k=0; k<nr-1; k++) { if(PIVOT(&num,nr,k,ma)!=0) return (1); if(num!=k) { cc=mb[num]; mb[num]=mb[k]; mb[k]=cc; } for(i=k+1; i<nr; i++) { cc=ma[nr*i+k]/ma[nr*k+k]; for(j=k+1; j<nr; j++) ma[nr*i+j]=ma[nr*i+j]-cc*ma[nr*k+j]; mb[i]=mb[i]-cc*mb[k]; } } for(k=nr-1; k>=0; k--) { if(fabs(ma[nr*k+k])<=EPS) return(1); cc=0.0; for(j=k+1; j<nr; j++) cc+=ma[nr*k+j]*mx[j]; mx[k]=(mb[k]-cc)/ma[nr*k+k]; } return (0); } return 0; }

  • 下記のc言語のプログラム(LU分解を用いた連立一次方程式)を起動させた

    下記のc言語のプログラム(LU分解を用いた連立一次方程式)を起動させたいのですがエラーがでてしまいます。 どのようにしたら動作しますか? #include <stdio.h> #include <stdlib.h> #include <float.h> #define MAX_DIM 10 #define MIN_DIM 1 int get_dimension(int, int); double *get_matrix( int ); double *get_vector( int ); void set_matrix( int, double* ); void set_vector( int, double* ); void LU( int, double*, double*, double* ); void L_equ( int, double*, double*, double* ); void U_equ( int, double*, double*, double* ); void pr_vector( int, double* ); void matrixcpy( int, double*, double* ); void make_I( int, double* ); void main( void ) { int n , i ; double *A, *b ; double *L, *U ; double *c, *x ; n = get_dimension( MAX_DIM, MIN_DIM ); if( ( A = get_matrix( n ) ) == (double *) NULL || ( L = get_matrix( n ) ) == (double *) NULL || ( U = get_matrix( n ) ) == (double *) NULL || ( b = get_vector( n ) ) == (double *) NULL || ( c = get_vector( n ) ) == (double *) NULL || ( x = get_vector( n ) ) == (double *) NULL ) { fprintf( stderr, "メモリ所得エラーです!!\n" ); } else { set_matrix( n, A ); set_vector( n, b ); LU( n, A, L, U ); L_equ( n, L, c, b ); U_equ( n, U, x, c ); printf( "解は、" ) ; pr_vector( n, x ) ; } }

  • C言語の宿題なのですが・・・

    問題は「ベクトルの和を求めよ。ただし入力部、出力部、計算部を手続き型で記述せよ」というものです。 例として、(1,2,3)と(4,5,6)と入力すると、(1+4,2+5,3+6)の計算で(5,7,9)が表示されるそうです。 ある程度自分でも書いてみたのですが、単純に計算部分の書き方が分からなかったり、その他の部分も不十分なようです。 //-------------------------------------------------------------- #pragma hdrstop //-------------------------------------------------------------- #pragma argsused #include<stdio.h> #include<conio.h> #define N 3 /*---Input Vector Function---*/ void ReadVector(int vec[N]) { int i; for(i=1;i<=N;i++) scanf("%d",&vec[]); } /*---Output Vector Function---*/ void WriteVector(int vec[]) { int i; for(i=1;i<=N;i++) printf("%d"vec[]); } /*---Plus Function of Vector---*/ void VecPlus(int vec1[],int vec2[],int vec3[]) { int i; for(i=1;i<=N;i++)   ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄         ?   ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ } /*---Main Program---*/ int main(void) { int Vector1[N+1],Vector2[N+1],Vector3[N+1]; ReadVector(vector1); ReadVector(vector2); VecPlus(vector1,vector2,vector3); WriteVector(vector3); getch(); return 0; } //-------------------------------------------------------------- もし宜しかったら、どなたかアドバイスしていただけませんでしょうか。 よろしくお願いいたします。

  • C言語の問題がわかりません。

    C言語の問題がわかりません。 ファイルを読み込んで、文字数と単語数を数えるプログラムなのですが、 例えば、ファイルが 「I was born in Japan  I like baseball」でしたら、 1:I was born in Japan 19文字、5単語 2:I like baseball 15文字、3単語 と表示したいのですが、下記のプログラムのままだと、 1:I was born in Japan 20文字、5単語 2:I like baseball 15文字、3単語 と作った文章の改行の部分を認証してしまいます。 改行の部分を認証しないようにこれを修正するにはどうしたらいいでしょうか? また、もう一つあるのですが、結果の文章を 1:napaJ・・・ 2:・・・ekil I と行ごとに逆に表示したいのですが、どうすれば逆に表示できますでしょうか? #include <stdio.h> #include <string.h> #include <stdlib.h> int main(void) { FILE *fin; char filename[20]; char data[256], *abc; int a,b,n; printf("ファイル名の入力 :"); scanf("%s", filename); fin=fopen(filename,"r"); if(fin == NULL){ printf("%sがオープンできません!\n",filename); exit(1); } a=0; b=0; n=0; while(fgets(data,256,fin) != NULL) { a=a+1; b=strlen(data); abc = data; *(abc - 2) = '\t'; while (*abc == ' ') {abc++;} while (*abc != '\0') { while (*abc != '\0' && !(*abc == ' ' || *abc == '\t' || *abc == ',' || *abc == '.')){abc++;} n = n+1; while (*abc != '\0' && (*abc == ' ' || *abc == '\t' || *abc == ',' || *abc == '.')) {abc++;} } printf("%d:%s\n",a,data); printf("%d文字、%d単語\n",b,n); n=0; } fclose(fin); return 0; }

  • c言語 可変長配列

    下は可変長配列のプログラムである.提供される可変長配列に文字列を格納するにはどのようにすればよいのでしょう.使い方の例を示していただけると助かります. #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <string.h> /* 可変長配列の初期サイズ */ #define INIT_SIZE 5 typedef struct vector Vector; typedef Vector *VectorPtr; /* 可変長型配列の構造体 */ struct vector { char **elems; /* 要素(文字列)の配列(固定長)*/ int size; /* 可変長配列のサイズ */ int capacity; /* 可変長配列の最大容量 */ }; /* 可変長配列を生成する */ VectorPtr create_vector(void) { VectorPtr v = NULL; v = malloc(sizeof(Vector)); if (v == NULL) { fprintf(stderr, "Couldn't allocate memory for a vector\n"); exit(EXIT_FAILURE); } v->elems = malloc(sizeof(char *) * INIT_SIZE); v->size = 0; /* 初期使用サイズは 0 */ v->capacity = INIT_SIZE; return v; } /* 可変長配列の実質的な解放作業を行う. * (次々と free() するので free() 後の NULL 代入は省略) */ void delete_vector0(VectorPtr v) { int i; /* free() と同様,NULLポインタに対しては何も行わない */ if (v == NULL) { return; } /* 各要素(文字列)の領域を解放 */ for (i = 0; i < v->size; i++) { free(v->elems[i]); } free(v->elems); /* 内部配列の領域を解放 */ free(v); /* 外側の枠も解放 */ } /* 可変長配列 v を初期化する(未使用状態にするだけで領域は解放しない).*/ void clear_vector(VectorPtr v) { int i; assert(v); /* 要素の各文字列を解放 */ for (i = 0; i < v->size; i++) { free(v->elems[i]); v->elems[i] = NULL; } /* 使用サイズを0にする */ v->size = 0; } /* 可変長配列 v を拡大する */ void expand_vector(VectorPtr v) { assert(v); /* 最大容量を2倍に増やす */ v->capacity *= 2; /* 新しい最大容量を持つ領域を確保 */ v->elems = realloc(v->elems, sizeof(char *) * v->capacity); /* サイズを変更できなかった場合のエラー処理 */ if (v->elems == NULL) { fprintf(stderr, "Couldn't re-allocate memory for a vector\n"); exit(EXIT_FAILURE); } } /* 可変長配列 v の最後に文字列 s を追加 */ void append(VectorPtr v, char *s) { assert(s); /* 容量が一杯になったら容量を拡大する */ if (v->size == v->capacity) { expand_vector(v); } v->elems[v->size] = _strdup(s); /* 最後に要素を追加 */ v->size++; /* 使用部分のサイズを1つ増やす */ } /* 可変長配列の(使用部分の)サイズを返す.*/ int get_vector_size(VectorPtr v) { assert(v); return v->size; } /* 可変長配列 v における添え字 index の要素(文字列)を取得 */ char *get_elem(VectorPtr v, int index) { assert(v); /* 配列添え字の範囲をチェック */ if (index < 0 || index >= v->size) { fprintf(stderr, "Index out of bounds"); exit(EXIT_FAILURE); } /* 指定された添え字の値を返す */ return v->elems[index]; } /* 可変長配列の内容を横に並べて表示する.*/ void print_vector(VectorPtr v) { int i; assert(v); if (v->size == 0) { printf("(empty)\n"); return; } for (i = 0; i < v->size; i++) { printf(">>%s", v->elems[i]); } printf("\n"); } int main(void) { return 0; }

  • C言語におけるローカル変数が使用するメモリについて

    例のようなC言語のプログラムを動かした場合、 確保されるメモリ領域はどうなるのでしょうか。 例 #include <stdio.h> int main(void) { int a = 0; } このとき、変数aはint型なのでスタック領域に4バイトのメモリが確保されると理解しています。 と同時にaという変数名と確保されたスタック領域の番地を紐づけるようなメモリがどこかに確保されるのではないかと思ってるのですが、この理解で正しいでしょうか。 またその場合は変数aの番地はどの領域に確保されるのでしょうか。 ご教示お願いいたします。

  • 昇順ソート

    sort.txtから読み込んだ値を 昇順でソートして出力するにはどうしたらよいでしょうか? #include <stdio.h> #include <stdlib.h> #include <string.h> #include <search.h> /* 比較関数 */ int strcmp_asc(const void *, const void *); int main(void) { FILE *fin, *fout; int i; int length; char s[256], s2[256]; if( (fin=fopen("sort.txt","r"))==NULL) { printf("入力ファイルがオープンできません\n"); exit(EXIT_FAILURE); } if( (fout=fopen("file2.txt","w"))==NULL) { printf("出力ファイルがオープンできません\n"); exit(EXIT_FAILURE); } while(fgets(s, 256, fin) != NULL) { /* 要素数を求める */ length = sizeof(s) / 256; /* 昇順でソート */ qsort(s, length, 256, strcmp_asc); /* memset(s2, NULL, sizeof(s2)); for (i = 0; i < length; i++) { } */ fprintf(fout,"%s\n",s2); } fclose(fin); fclose(fout); return 0; } int strcmp_asc(const void *sa, const void *sb) { return strcmp((char *)sa, (char *)sb); } sort.txt 50 45 35 25 15 10 5 1 32 46 8 7 9 19 18 14 16 13 12 17 11 20 40 30 31 3 2 37 38 36 33 39 34 49 47 48 4 6 44 42 43 41 21 22 26 24 28 29 27 23

  • C++で領域の確保の方法

    今C++の勉強中なのですが、 領域の確保の方法でいい方法が知りたいのです。 ポインターのポインターを使って二次元配列の領域を確保したいのですがいい方法が思いつきません。 int **pBox; pBox = new int *[ 10 ]; for( int i=0; i<10; i++ ) { pBox[ i ] = new int[10]; } //ちなみに今はこんな感じのものしか考え付きませんint型[10][10] を確保したつもりです。 間違っていたら教えていただきたいです。 本題はこちらで、もっと効率のいい確保の方法を知りたいのでご協力を よろしくお願いします。

  • クイックソート(C言語)

    こんにちは<_ _> クイックソートについての質問です。 左端を軸にクイックソートでデータを昇順にソートする プログラムを作ったのですがうまく動きません #include<stdio.h> void quick(int *,int,int); #define N 10 int main(void) { static int a[]={41,24,76,11,45,64,21,69,19,36}; int k,b=0; quick(a,0,N-1); for(k=0;k<N;k++) printf(" %d",a[k]); return 0; } void quick(int a[],int left,int right) { int s,t,i,j; t=right; i=left+1; j=a[left]; if(right>left){ while(1){ while(a[++i]>j); while(a[--t]<j && t>0); if(i>=t){ break; } s=a[i]; a[i]=a[t]; a[t]=s; } s=a[i]; a[i]=j; a[left]=s; quick(a,left,t-1); quick(a,t+1,right); } } 値の入れ替え、軸の入れ替えもしましたが結果として 「41 41 76 69 45 64 41 19 0 36」 このような結果で出力されてしまいます・・・ 時間に余裕のある方いましたらご指導をお願いします。 よろしくお願いします。<_ _>

生活防衛資金の必要額とは
このQ&Aのポイント
  • 生活防衛資金とは老後のために必要な最低限の貯金のことです。
  • 独身で一人暮らしの場合、生活防衛資金はどれくらい用意すれば良いのでしょうか?
  • 一般的には年間の生活費の3~6ヶ月分程度の貯金が必要とされています。
回答を見る

専門家に質問してみよう