• ベストアンサー

3次元配列使用でStackOverflowException発生

C++で3次元配列を使用したいのですが,強制終了させられてしまいます. おそらくスタックオーバーフローというものが起こっているようなのですが, double L[10][500][30],a[10][500][30],b[10][500][30],… というふうに, 10*500*30の要素数の配列を全部で10種類使用するのはやはりメモリ的に無理があるのでしょうか? コード作成はVisual Studio 2008,コンパイラはgccで実行しています. あまりこの要素数は減らしたくないのですが, 何か解決策があれば教えてください. ------------------------------------------------------------ 環境:WinXP, メモリ1GB, Pentium4 ちなみに,いくつか対策を講じて見ましたが,エラーが出てしまった例を一応下に載せておきます. <VisualStudioでデバッグ有りのコンパイル> エラー."System.StackOverflowException' のハンドルされていない例外が発生しました" <new()を使用した配列の動的確保> double ***L, ***a, ・・・; L = new double**[30];// double型30個分の領域を動的確保 a = new double**[30]; … for(k=0; k<=30; k++){ L[k] = new double*[500];// double型500個分の領域を動的確保 a[k] = new double*[500]; ・・・} for(k=0; k<=30; k++){ for(j=0;j<=500; j++){ ☆L[j][k] = new double[10];// double型10個分の領域を動的確保 a[j][k] = new double[10]; ・・・}} ☆:エラー発生."保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。"

  • b044
  • お礼率100% (5/5)

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

  • ベストアンサー
  • zwi
  • ベストアンサー率56% (730/1282)
回答No.2

ローカル変数はスタックに格納されます。スタック上に1MB越えをする配列を10個とる事など大体のOSの実装では想定されていません。 グローバル変数か、newかmallocでの確保が必要です。 でnewでの確保の失敗ですが、 ☆L[j][k] = new double[10];// double型10個分の領域を動的確保 a[j][k] = new double[10]; 添え字のjとkが逆ですよ。 今のプログラムだとL[30][500][10]の配列としてアクセスする必要があります。元のdouble L[10][500][30]と逆になっているのでプログラムを直したほうが良いですよ。

b044
質問者

お礼

ありがとうございます! 添え字が逆との指摘,修正したら確保できました。 お礼が遅くなってしまいましたが, ありがとうございました!

その他の回答 (2)

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.3

>System.StackOverflowException スタックサイズはコンパイラによって設定可能です。 GCCやVCではデフォルト1MBとされていますが、 環境によっては変更できないので、お勧めできません。 > L[j][k] = new double[10];// 既に出てますが、ここで普通に アクセス違反していますね。 正しくはL[k][j]。

b044
質問者

お礼

ありがとうございます! お礼が遅くなってしまいましたが, 無事確保できました!

noname#208124
noname#208124
回答No.1

普通にmalloc使いましょうよ スタックを12MBも要求するなんてコードレビューで間違いなく糞コード認定ですよ

b044
質問者

お礼

ありがとうございます! それまでmallocもnewも恥ずかしながら存在すら知らなかったのですが 今回はnewの方を使用しました

関連するQ&A

  • 多次元配列の動的メモリ

    1次の配列aの動的メモリは例えば 「double *a;  int num = 3; //配列の数  a = new double [3];」 などとすれば確保できることは分かるのですが、 二次元配列など、多次元配列の動的メモリは どのようにすれば確保できるのですか?

  • 配列を用いたリストでは使用されない領域が発生する?

    応用情報技術者試験に絡んだ質問です。 まずは問題をご覧ください: 問題 リストには,配列で実現する場合とポインタで実現する場合とがある。リストを配列で実現した場合の特徴として,適切なものはどれか。ここで,配列を用いたリストは配列に要素を連続して格納することによってリストを構成し,ポインタを用いたリストは要素と次の要素へのポインタを用いることによってリストを構成するものとする。 正解の選択肢はこれ↓: リストにある実際の要素数にかかわらず,リストに入れられる要素の最大個数に対応した領域を確保し,実際には使用されない領域が発生する可能性がある。 解説: 配列で実現するリストの特徴です。配列を用いる場合は最大の要素数を格納できるだけのメモリ領域をあらかじめ確保する必要があります。1,000要素分確保しても実際の格納数が10要素程度だとすると、残りの990要素分のメモリ領域が無駄になってしまいます。 ・・・これって正しいですか? mallocで動的にメモリを確保して配列を作り、後にreallocで要素数を増やすことで無駄のない運用ができるはずです。自分はそれを知っていたので、この選択肢を選びませんでした。「可能性がある」で逃げてますが、それを言うなら、無駄なく使える可能性もあるわけで…。この問題、納得いかないです。 まずはmallocとreallocで動的に確保できることへの回答をお願いします。それから、この問題の妥当性についてお願いします。

  • 2次元配列の動的確保について

    共分散行列を2次元配列に格納しようとしているのですが、 その要素は、左下半分と右上半分が同じになるため 対角要素と、どちらか半分だけを格納してメモリを節約したいと考えています。 以下のように動的確保することでメモリは節約できているでしょうか? if( (a = (double **)malloc(sizeof(double *) * (N) ))==NULL ){ fprintf(stderr, "error malloc for a\n"); exit(0); } for( i=0; i<NN; i++ ){ if( ( a[i] = (double *)malloc(sizeof(double) * (i+1) ))==NULL ){ fprintf(stderr, "error malloc for a\n"); exit(0); } } *節約しない場合は、i+1 が N になります。 確保できているのなら、どのように参照すればいいのでしょうか?データの並び(?)は、a[0][0],a[1][0],a[1][1],a[2][0],a[2][1],a[2][2],,,というように並んでいるでしょうか? 例えば、a[0][1]を参照しようとすると、シグメンテーションフォルトなど起こりうるでしょうか。必要であれば、上プログラム内Nは、3000程度と考えてください。 そして、もし他にメモリを節約する上で良い方法があれば、ご教授していただけたらと思います。 よろしくお願い致します。

  • Javaの二次元配列についてです

    配列要素を 1, 2, 3, 4, 5 2, 2, 3, 4, 5 3, 3, 3, 4, 5 4, 4, 4, 4, 5 5, 5, 5, 5, 5 のようにしたいのですがどうすればよろしいでしょうか? int[][] a = new int[5][5]; for (int i = 0; i < a.length; i++) { for (int j = 0; j < a[i].length; j++) { ~ここの処理を教えてください~ } }

    • ベストアンサー
    • Java
  • 1次元配列と2次元配列のアドレスについて

    2次元a[2][3]と同じ分の1次元配列b[2*3]を確保して、常に a[0][0]=b[0] a[0][1]=b[1] a[0][2]=b[2] a[1][0]=b[3] a[1][1]=b[4] a[1][2]=b[5] となるようにしたいです。 たとえば、a[0][0]=100;としたら一緒にb[0]=100になるような状態です。 自分ではそれぞれ同じアドレスを参照するようにすればできると思ったんですが、その方法がわかりません。 ためしに、 int a[2][3],b[2*3]; を宣言して a=b;としてみたり、 for(i=0;i<2;i++){ for(j=0;j<3;j++){ &a[i][j]=&b[j+i*3]; } } などやってみたのですが、これだとエラーがでてしまいどうしたらいいかわかりません。 どうしたら出来るのかアドバイスお願いします。

  • サイズがいろいろの2次元配列を数多く発生させる方法

    2次元配列は、すなわちマトリックスということになります。2次元配列を数多く発生させるために3次元配列が定義できると楽になります。しかし、2次元のマトリックスのサイズが異なる場合、どうなるでしょうか。 例えばA(i,j,k)ですが、i=1の場合、i=2の場合、....でj,kの取る範囲が異なるということなのですが。最大にとっておけばいい、ということにはなりますが、使わないメモリを確保することにちょっと抵抗があるのですが。言語はFortranなので難しい面があると思います。C言語だったらmallocを使うんだろうと思いますが。

  • 三次元配列の動的メモリの確保?

    const int SLICE=2; const int SIZE=256; signed short int *matrix=new signed short int[SLICE][SIZE][SIZE]; for(int i=0; i<SLICE; i++){ for(int j=0; j<SIZE; j++){ for(int k=0; k<SIZE; k++){ fin.read((char*) &matrix[SLICE][SIZE][SIZE],sizeof(signed short int)); } } } delete[] data; 三次元データを読み込むために、三次元配列を使って読み込もうとしたのですが、上手く読み込めません。 三行目の所で、error C2440: '初期化中' : 'short (*)[256][256]' から 'short *' に変換できません。 七行目の所で、error C2109: 配列または、ポインタでない変数に添字が使われました。 というエラーがでます。動的メモリの確保の仕方がまずいのでしょうか? どなたか教えて頂けますでしょうか?よろしくお願いします。

  • 配列のエラーに関して

    java言語を用いて,Householder変換を用いた固有値の数値計算に挑戦してみました.しかし,次のようなエラーが発生し上手くいきません.どなたかこの問題を解決するためにお力をかしていただけないでしょうか. ----------エラー内容-------------------------------------------------------------------------------- Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0 at Out.Mhouse(House.java:90) at House.main(House.java:10) ---------------------------------------------------------------------------------------------------- //Householder変換 public class House{ public static void main(String[] args){ double[][] A = new double[3][3]; int n = A.length; Out out = new Out(); for(int i = 0;i < n;i++){ for(int j = 0;j < n;j++){ if(j < n-1){ System.out.print(out.Mhouse(A)[i][j] + " "); }else if (j == n-1) System.out.println(out.Mhouse(A)[i][j]); }; }; }; }; class Out{ double[][] outpro(double[] x){ int n; n = x.length; double[][] A = new double[n][n]; for(int i = 0;i < n;i++ ){ for(int j = 0;j < n;j++){ A[i][j] = x[i] * x[j]; } } return A; }; double[][] Msca(double a,double[][] A){ int n = A.length; for(int i = 0;i < n; i++){ for(int j = 0;j < n;j++){ A[i][j] = a * A[i][j]; } } return A; }; double selfpro(double[] x){ double a = 0; int n = x.length; for(int i = 0;i < n; i++){ a = a + x[i] * x[i]; }; return a; }; double[] minus(double[] x, double[] y){ int n = x.length; double[] z = new double[n]; for(int i = 0;i < n;i++){ z[i] = x[i] - y[i]; }; return z; }; double[][] house_1(double[] x){ int n = x.length; double[][] A = new double[n][n]; for(int i=0;i < n;i++){ for(int j = 0;j < n;j++){ if(i == j){ A[i][j] = 1 - Msca(2/selfpro(x),outpro(x))[i][j]; }else{ A[i][j] = - Msca(2/selfpro(x),outpro(x))[i][j]; }; }; }; return A; }; double[][] house_2(double[] x){ double[][] z = new double[1][1]; z[1][1] = 1 - 2; return z; }; double[][] Mhouse(double[][] A){ int n = A.length; double[][] H = new double[n][n]; for(int i = 0;i < n;i++){ double[] x = new double[n-i]; double[] y = new double[n-i]; double[][][] L = new double[i][n-i][n-i]; for(int j = 0;j < n-i;j++){ x[j] = A[i][i+j]; if(j == 0){ y[j] = 1; }else{ y[j] = 0; }; x[j] = y[j] - x[j]; }; if(i < n-1){ L[i] = house_1(x); for(int k = 0;k < n-i;k++){ for(int l = 0;l < n-i;l++){ H[i+k][i+l] = L[i][k][l]; }; }; }else if(i == n-1){ L[i] = house_2(x); for(int k = 0;k < n-i;k++){ for(int l = 0;l < n-i;l++){ H[i+k][i+l] = L[i][k][l]; }; }; }; }; double[][] B = new double[n][n]; for(int i = 0;i < n;i++){ for(int j = 0;j < n;j++){ for(int k = 0;k < n;k++){ B[i][j] = H[i][k] * A[k][j]; }; }; }; return A; }; };

    • ベストアンサー
    • Java
  • 動的配列

    二次元配列を動的に確保したいのですが,初歩的なところでつまづいてしまいました. どなたかご教授ください. C++ Builder 6を使用しております. SumF[5][40]と確保したいのです. 以下,プログラムです. ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ double **SumF; SumF = new double *[5]; for(int p = 0; p < 5; p++){ SumF[p] = new double [40]; for(int q = 0; q < 40; q++){ SumF[p][q] = new double; } } ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 「浮動小数点の不正な使用」とエラーがでます. よろしくお願いいたします.

  • 多次元配列とfor文について

    javascriptの配列について質問です。 例えば: var arrXXX = new Array(); function samplefunc{ //3次元配列の種類の作成 for (m = 0; m < aaa.length ; m++) { //連想配列作成 arrXXX .push(aaa[m]); } for (j = 0; j < bbb.length; j++) { for (i = 0; i < ccc.length; i++) { arrXXX[aaa[j]] = new Array(ccc.length); arrXXX[aaa[j]][i] = new Array(ccc.length); for (k = 0; k < ddd.length; k++) { arrXXX[aaa[j]][i][k] = eee;     ここでは配列を適切に使える・・・ } } } ここでarrXXXを使いたいが、3次元配列でなくなっている?!  arrXXX[~][0][0]はnullまたはオブジェクトではありません・・・がでます。 } 結局、for文を完全にでてしまうと、せっかくつくった配列がダメになってしまいます。どうすればfor文外で配列を使用できるのか教えてください!