2016-07-25 8 views
1

私は "2 x反復"サイズの3つの行列を満たす必要があるシミュレーションを実行しようとしていました。これは(反復=)10^8列と2行です。私はまた、サイズ10^8のベクトルtで動作します。動的メモリ割り当てを使用して、私は次のコードを書いた:ダイナミックメモリ割り当てを使用してCで行列を扱うには?

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

#define T 10000 
#define dt 0.0001 
#define iterations (T/dt) 

/*(more code)*/ 
int main(){ 
    int i, j; 
    double *t; 
    double (*x)[2], (*y)[2], (*c)[2]; 

    t=(double *) malloc((iterations-1)*sizeof(double)); 
    x=(double (*)[2]) malloc((2*(iterations))*sizeof(double)); 
    y=(double (*)[2]) malloc((2*(iterations))*sizeof(double)); 
    c=(double (*)[2]) malloc((2*(iterations))*sizeof(double)); 

    for(i=0; i=1; i++){ 
    x[i][0]=50+500*i; 
    y[i][0]=300; 
    c[i][0]=15; 
    } 

    for(j=0; j<=iterations-2; j++){ 
    t[j+1]=t[j]+dt; 
    /*(more code)*/ 
    printf("%G %G %G %G %G %G\n",x[0][j+1],x[1][j+1],y[0][j+1],y[1][j+1],c[0][j+1],c[1][j+1]); 
    } 
    return 0; 
} 

ダイナミックメモリ割り当ては正しく書かれていますか?私は実際に、サイズ "反復"のベクトルtとサイズ "2 x反復"の3つの行列を持っていますか?

そして、行列の各要素を塗りたい場合、たとえば行列xの位置(1,4)に50を入れたいとしたら、x [1] [4] = 50? (最初の "for"のように)

問題は、プログラムを実行するとエラーが発生するということです。セグメント化エラーです。次に、デバッガを使用して次のようになります。

プログラム受信信号SIGSEGV、セグメンテーションフォルト。

X [0] [0] = 50

+0

エラーと最適化を除いて、単純に2つの変数 'x1'と' x2'を使用すると、読みやすさが大幅に向上します。 – Phillip

+4

1) 'malloc'&friendsの結果をキャストしないでください。 2)マジックナンバーを使用しないでください。 3)これはコードレビューサービスではありません。あなたの**具体的な**問題は何ですか? 4)注意: 'sizeof(* x)'等は配列中の1つのエントリのサイズをいつものように与えます。 – Olaf

+0

1つの行列の代わりに2つのベクトルを書きますか?膨大な量のデータと多数のデータを扱っているので、本当に最適なコードが必要です。最初はOctaveで同じシミュレーションを書いていましたが、パラメータに特定の値を設定すると、プログラムは約8時間実行された後にハングアップしました... 特定の問題は、プログラムを実行するとエラーセグメンテーションフォールト( 'コア'が拒否される)が発生するということです –

答えて

1

行列を割り当てるための汎用的な方法:

double **mat_init(int n_rows, int n_cols) 
{ 
    double **m; 
    int i; 
    m = (double**)malloc(n_rows * sizeof(double*)); 
    for (i = 0; i < n_rows; ++i) 
     m[i] = (double*)calloc(n_cols, sizeof(double)); 
    return m; 
}  
void mat_destroy(int n_rows, double **m) 
{ 
    int i; 
    for (i = 0; i < n_rows; ++i) free(m[i]); 
    free(m); 
} 

これも行うことができます:

double **mat_init2(int n_rows, int n_cols) 
{ 
    double **m; 
    int i; 
    m = (double**)malloc(n_rows * sizeof(double*)); 
    m[0] = (double*)calloc(n_rows * n_cols, sizeof(double)); 
    for (i = 1; i < n_rows; ++i) 
     m[i] = m[i-1] + n_cols; 
    return m; 
}  
void mat_destroy2(double **m) 
{ 
    free(m[0]); free(m); 
} 

上記の両方の方法では、matrix[row][col]を使用してセルにアクセスできます。場合によっては、単一の配列を割り当て、セルにアクセスするためにmatrix[row*n_cols+col]を使用することをお勧めします。

ところで、誰かが「キャストを使わないでください」と言うでしょうが、キャストを使うことのメリットがあります。それは話題にはなりません。

+0

私はmallocとcallocの戻り値をチェックしたいと思います(宗教戦争を始めるのではなく、 'double ** m = malloc(n_rows * sizeof * m);'を使うことをお勧めします)。ポインタは破壊関数に渡されました。なぜなら、NULLポインタを解放することはOKですが、NULLポインタ(m [i]またはm [0])を参照解除するのは実行時エラーです。 –

1

I mean, do I really have a vector t of size "iterations"

t=(double *) malloc((iterations-1)*sizeof(double)); 
          ^^^ 

使用すると、1つを引くので、答えはノーです。

.... and the three matrices of size "2 x iterations"?

さて、あなたは「2 x反復」というサイズの3つの行列を持っています。あなたは「イテレーション」行2列を持っている

double m[iterations][2]; 

:しかし、何を持っていることと等価です。

ですから、のようにアクセスに "メモリ不足" のために常にチェック、すなわち

p = malloc(....); 
if (p == NULL) 
{ 
    printf("out of mem\n"); 
    return -1; 
} 

を忘れないでください:

m[0][0] 
m[0][1] 
m[1][0] 
m[1][1] 
m[2][0] 
m[2][1] 
m[3][0] 
...... 
+1

OPは "10^8列と2行" _を要求しますが、 'double(* x)[2]'を宣言し、 'x =(double(*)[2])malloc((2 *(反復))* sizeof(double));' ... –

+0

ありがとう! @ 4386427、あなたは 'double m [2] [iterations]'を意味します、そうですか? 問題は、セグメンテーションフォールトエラーが発生し、デバッガを使用して次のようになることです。 プログラム受信信号SIGSEGV、セグメンテーションフォルト。 x [0] [0] = 50; そして私は何が間違っているのか分かりません... –

+0

@ S.Proa - いいえ、私は実際に書かれていることを意味します。あなたはメモリがない限り、 'x [0] [0]'には問題がありません。更新された回答をご覧ください。 – 4386427

関連する問題