2016-12-08 13 views
1

私は大きな配列のアルゴリズムを実装していますが、Nが820を超えると、メモリのためにセグメンテーションフォールトの問題(コアダンプ)が発生します。私は私のコードを実装するために3つの大きな配列を使用します。このエラーを修正するにはどうすればよいですか?Cプログラムのメモリが不足しています

#define N 400 

void upper(float A[N][N], float x[N], float b[N]) 
{ 
    int i,j; 
    float sum; 
    x[N-1] = b[N-1]/A[N-1][N-1]; 

    for(i=N-2; i>=0; i--){ 
     sum = b[i]; 
     for(j=i+1; j<N; j++){ 
      sum = sum - x[j]*A[i][j]; 
     } 
     x[i] = sum /A[i][i]; 
    } 
} 

void lower(float A[N][N], float x[N], float b[N]) 
{ 
    int i,j; 
    float sum; 
    x[0] = b[0]/A[0][0]; 
    for(i=1; i<N; i++){ 
     sum = b[i]; 
     for(j=0; j<i; j++){ 
      sum = sum - x[j]*A[i][j]; 
     } 
     x[i] = sum /A[i][i]; 
    } 
} 


void cholesky(float A[N][N],float L[N][N]) 
{ 
    int i,j,k; 
    float sum; 

    for(i=0; i<N; i++){ 
     for(j=i-4; j<i; j++){ //j-4 because i have 0 and i want to do less computations 
      if(j<0) 
       continue; 
      sum = A[i][j]; 
      for(k=i-4; k<i; k++){ 
       if(k>=0) 
        sum = sum - L[i][k]*L[j][k]; 
      } 
      L[i][j] = sum /L[j][j]; 
     } 
     sum = A[i][i]; 
     for(k=i-4; k<i; k++){ 
      if(k>=0) 
       sum = sum - L[i][k]*L[i][k]; 
     } 
     L[i][i] = sqrt(sum); 
    } 
} 

void transpose(float L[N][N], float LT[N][N]) 
{ 
    int i,j; 
    for(i=0; i<N; i++){ 
     for(j=0; j<N; j++){ 
      LT[i][j] = L[j][i]; 
     } 
    } 
} 

void table(float A[N][N], float aii, float aone, float athree) 
{ 
    int i,j; 

    for(i=0; i<N; i++){ 
     for(j=0; j<N; j++){ 
      if(i==j){ 
       A[i][j] = aii; 
      } 
      else if((i+1 ==j) || (i-1==j)){ 
       A[i][j] = aone; 
      } 
      else if(i+3==j || i-3==j){ 
       A[i][j] = athree; 
      } 
      else{ 
       A[i][j] = 0; 
      } 
     } 
    } 
} 

void vector(float b[N], float b1, float b2, float all) 
{ 
    int i; 
    for(i=0; i<N; i++){ 
     b[i] = all; 
    } 
    b[0] = b[N-1] = b1; 
    b[1] = b[N-2] = b2; 
    b[2] = b[N-3] = b2; 
} 

int main() 
{ 
    float A[N][N]; 
    float L[N][N],LT[N][N]; 
    float x[N]; 
    float y[N]; 
    float b[N]; 
    int i,j; 

    table(A,12,-5,1); 
    vector(b,4,-1,0); 

    table(L,0,0,0); 
    cholesky(A,L); 
    transpose(L,LT); 
    lower(L,y,b); 
    upper(LT,x,y); 

    for(i=0; i<N; i++){ 
     printf("%f\n",x[i]); 
    } 
} 
+0

あなたは3つの行列と、スタック上の3つのベクトルを定義します。 'N'が大きいときにスタックオーバーフローが発生する可能性があります。 'malloc'を使ってヒープ上で大きな配列を動的に割り当てることができます。 –

+0

セグメンテーションフォールトは、配列を宣言する 'main'関数から来ています。これらの変数はスタック上で宣言されていますが、変数がそのサイズを超えている場合は、Linux/UNIXを使用している場合にはシェルプロンプトで 'ulimit -a'(linux/unixを使用している場合は通常は4kまたは8k)スペースを動的に割り当てるか、 'ulimit -s'を使ってスタックサイズを増やし、コードの上限をより高い 'N'に「プッシュ」するかどうか確認しなければなりません。そうでなければ 'malloc'を使って明示的にメモリを割り当てます –

答えて

1

大きな行列をmainに割り当てます。 Nが840の場合、各マトリックスは約2.8MB必要です。スタックはこれらの行列に対応できず、オーバーフローします。

あなたはあなたのシステムのスタック設定をいじることができますが、ヒープ上に大行列とベクトルを割り当てるために通常より良いです:

float (*A)[N] = malloc(N * sizeof(*A)); 
float (*L)[N] = malloc(N * sizeof(*L)); 
float (*LT)[N] = malloc(N * sizeof(*LT)); 
float *x = malloc(N * sizeof(*x)); 
float *y = malloc(N * sizeof(*y)); 
float *b = malloc(N * sizeof(*b)); 

は、すべての配列は、それらを使用する前に適切に配分されていることを確認します。

if ((A && L && LT && x && y && b) == 0) { 
    fprintf(stderr, "Allocation failed.\n"); 
    exit(1); 
} 

あなたがmainの終わりにそれらを使用した後にリソースをクリーンアップすることを忘れないでください:

free(A); 
free(L); 
free(LT); 
free(x); 
free(y); 
free(b); 
0

セグメント違反は、スタックのオーバーフローによって発生します。代わりにヒープを使用できます。ヒープを使用する簡単な方法は、配列をグローバルスコープで宣言することです。

は、明示的にヒープを使用してこの回答を参照してください。https://stackoverflow.com/a/571961/2791719

関連する問題