- ベストアンサー
C言語のオーバーフローについて
- C言語でのオーバーフローに関する問題を解決する方法を教えてください。
- csvファイルのデータを読み取り、計算させるプログラムで、行数が増えると「StuckOverFlowReception」というエラーメッセージが表示されます。
- 静的に領域を確保していることが原因かもしれませんが、具体的にどこがオーバーフローしているのか、修正方法を教えてください。プログラム初心者なので、分かりやすく教えていただけると助かります。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
「StuckOverFlow」辺りで検索すると出てくると思いますが……。 一般的にローカル変数はスタック領域に作成される事が多いです。 そして、VisualStudioではスタック領域は1M程度確保される場合が多いようです。 そんなワケで、「ローカル変数に大量のメモリを使用する」と、スタックオーバーフローになることがあります。 対処方法は3通り…ですかね。 ・リンカーオプションでスタック領域を大きくする。(どっかで限界来ますけどねぇ…) ・グローバル変数にする。(どっからでも書き換えできてウマー。知らないうちに書き換えられてあれぇ???) ・静的変数にする。(グローバル変数よりはマシでしょう) ・ヒープ領域から動的確保する。(ポインタ使う事になりますが。多次元配列だと工夫が必要でしょう。) ヒープから確保する。ってのが一般的な対処方法でしょうね。 次点が静的変数でしょうか。 # double a[N][M+30], b[N][M], c[N][M], w[4][32]; ではなく # static double a[N][M+30], b[N][M], c[N][M], w[4][32]; となる。
その他の回答 (5)
- honor
- ベストアンサー率35% (25/71)
「1度に使うのが1行」なら csvのデータを全部読み込んでから纏めて計算するのではなく csvのデータを1行読み込んでその行を計算して出力→次の行を読み込む というふうにすればいいということではないでしょうか。
お礼
あー、なるほど! データを格納して残していくのではなく、1行計算したら、上から書き換えていくってことですね?確かにそれなら1行分の領域を確保するだけで済みますね。かなりいい考え方ですね。ありがとうございます!
- Tacosan
- ベストアンサー率23% (3656/15482)
「数百行あるので、なるべく沢山で計算できたらと…」の意味がさっぱり分からない. 何百万行あろうと「一度に 1行しか使わない」のであれば「今現在の処理に必要な 1行」だけをおぼえておけばいい. 少なくとも, この質問で挙がっているプログラムについてはその通りでしょ? ついでにいうと, 場合によっては fgets を使わなくて済むかもしれない.
お礼
すいません。つまり、「1行計算して出力」を1度の実行で何行分もやりたいってことです。要は、何度も実行するのがめんどくさいっていうわがまま…もしかして、1行計算できれば、もっと簡単な方法で多数の行を計算できる方法があるっていうことですが? だとすれば自分の勉強不足が甚だしいですね。申し訳ないです。 とりあえず静的変数にして行数は増えました。 考えてくださりありがとうございます!
- Tacosan
- ベストアンサー率23% (3656/15482)
a に入れるべきデータを, なぜ全部読み込まなければならないのですか?
補足
列は2048データ固定で、wevelet変換という1行まるまる使って計算する手法を使ってます。なので、行に関しては、何度も同じ計算をして、最終的に同csvにコピーすればいいのですが、数百行あるので、なるべく沢山で計算できたらと…
- maiko0318
- ベストアンサー率21% (1483/6969)
Mは本当は2048もいらないのでは? だったら malloc を勉強して動的にとれば実際のデータ分だけで済みます。
補足
データは2048個固定です。 一応 char buff[] → char *buff; while(fgets(buff, 30000, IN1) != NULL){ buff = (char*)malloc(30000); pbuff = buff; while((pbuff = strtok(pbuff, ",\n")) != NULL){ a[i][j++] = strtod(pbuff, NULL); pbuff = NULL; } i++; j=0; free(buff); } でやったのですが、同じでした。
double a[N][M+30], b[N][M], c[N][M], w[4][32]; //配列の領域を定義 この行の領域割り当てが多きすぎるので、これを、 double a[N][M+30], b[N][M], c[N][M], w[4][32]; //配列の領域を定義 main() { } と、mainの外、しかし、同一ファイル内に移してみて下さい。
お礼
参考書に、1つの関数に詰め込みすぎると予期せぬことが起こりやすいと書いてありました。やはりそれも原因の1つなのでしょうか。ご指摘のように関数を変えたり、より計算が楽になるような工夫をしてみようと思います。 ご指摘ありがとうございます!
お礼
スタック領域を増やすことは検討したのですが、やはり限界があることから、動的に確保すべきかもしれません。ただ、原因の変数がわかれば、それだけの変更でよかったのですが、わからないだけに、とりあえずプログラム書き換えよう… と、思って、試しで静的変数にしたとたん一気に行数が増えました!確認したまでで200までいけます。 staticなので格納領域が毎度初期化されない?からよかったのでしょうか? とにかく、策をわざわざ考えていただきありがとうございます!