ページ 11

サイズの大きい配列の生成

Posted: 2012年1月13日(金) 10:27
by perseus
自分は今、とあるサイズの大きい配列を生成したいのですが、コンパイルは通るのですが実行するとエラーが出てしまい、配列が出力されません。
ソースコードは以下のとおりです。

コード:

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

#define NA 11

int main(void)
{
    int NB = NA - 1;     
    int an = pow(2,NB);  
    int NC = an / 2;  
    int a[an][an];
    int l,k,m;
    for(l=0;l<an;l++)  for(k=0;k<an;k++)  a[l][k]=0;
    k = 0;
    for(l=0;l<NC;l++){
        a[l][k]=1;
        a[l][k+1]=1;
        k=k+2;
    }
    k = 0;
    for(l=NC;l<an;l++){
        a[l][k]=1;
        a[l][k+1]=1;
        k=k+2;
    }
    a[0][0]=0;
    for(l=0;l<an;l++){
        for(k=0;k<an;k++){
            for(m=0;m<NA-2;m++){
                if ((k >> m) & 1 != 0) { 
                    if((k >> (m+1)) & 1 != 0) {
                        a[l][k]=0;
                        a[k][l]=0;
                    }
                }
            }
        }
    }
    printf("a[%d][%d]={",an,an);
    for(l=0;l<an;l++){
        printf("{");
        for(k=0;k<an;k++){
            printf("%d",a[l][k]);
            if(k!=an-1){
                printf(",");
            }else{
                printf("}");
                if(l!=an-1) printf(",");
            }
        }
        if(l!=an-1) printf("\n               ");
    }
    printf("};\n");
}
これで出力されるはずの配列はa[1024][1024]となるはずです。

コード:

#define NA 10
として、NA=10の場合のa[512][512]は正しく出力されるのを確認しています。
エラーメッセージは以下のとおりです。
_cygtls:handle_exceptions: Erorr while dumpting state (probably corrupted stack)
Segmentation fault (core dumped)
環境はWindows XP での Cygwin 上での実行です。
NA=11で正しく出力するにはどうしたらいいでしょうか? 教えてください。

Re: サイズの大きい配列の生成

Posted: 2012年1月13日(金) 10:32
by softya(ソフト屋)
ローカル変数で巨大な配列は作れませんのでnewで動的確保をして下さい。C言語の文法の範囲ならmallocを使いましょう。

Re: サイズの大きい配列の生成

Posted: 2012年1月13日(金) 11:05
by persens
ありがとうございます!
以下のように修正したら、出力されました。

コード:

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

#define NA 11

int main(void)
{
    int NB = NA - 1;     
    int an = pow(2,NB);  
    int NC = an / 2; 
    int l,k,m; 
    int **a;
    a = (int **)malloc(sizeof(int *)*an);
    for (l=0;l<an;l++){
        a[l]=(int *)malloc(sizeof(int)*an);
    }
    for(l=0;l<an;l++)  for(k=0;k<an;k++)  a[l][k]=0;

    k = 0;
    for(l=0;l<NC;l++){
        a[l][k]=1;
        a[l][k+1]=1;
        k=k+2;
    }
    k = 0;
    for(l=NC;l<an;l++){
        a[l][k]=1;
        a[l][k+1]=1;
        k=k+2;
    }
    a[0][0]=0;
    for(l=0;l<an;l++){
        for(k=0;k<an;k++){
            for(m=0;m<NA-2;m++){
                if ((k >> m) & 1 != 0) { 
                    if((k >> (m+1)) & 1 != 0) {
                        a[l][k]=0;
                        a[k][l]=0;
                    }
                }
            }
        }
    }
    printf("a[%d][%d]={",an,an);
    for(l=0;l<an;l++){
        printf("{");
        for(k=0;k<an;k++){
            printf("%d",a[l][k]);
            if(k!=an-1){
                printf(",");
            }else{
                printf("}");
                if(l!=an-1) printf(",");
            }
        }
        if(l!=an-1) printf("\n                   ");
    }
    printf("};\n");
    free(a);
}

Re: サイズの大きい配列の生成

Posted: 2012年1月13日(金) 11:30
by たかぎ
解決したみたいなのでよいのですが、今回程度の内容であれば、mallocを使うよりstaticを付けて静的な配列にするほうがずっと簡単です。

Re: サイズの大きい配列の生成

Posted: 2012年1月13日(金) 16:13
by YuO
提示されたプログラムのようにそのまま終了するのであれば問題ないですが,
関数の一部として使うのであれば,a[0] ... a[an - 1]をfreeしていないのは問題になり得ます。
記憶域は残念ながら無限ではないので,突然mallocがNULLを返し,エラー or 誤動作し始めます。

static使えばこの問題はもちろん解決しますし (マルチスレッドを考えない場合),

コード:

for (int i = 0; i < an; ++i) free(a[i]);

コード:

free(a);
の前にいれることでも解決します。