【C言語】スタック領域について

C言語関連 | プログラミング307閲覧xmlns="http://www.w3.org/2000/svg">100

ベストアンサー

この回答はいかがでしたか? リアクションしてみよう

ThanksImg質問者からのお礼コメント

ありがとうございました。 勉強になりました

お礼日時:11/24 20:02

その他の回答(7件)

①それをいちいち気にしていたら高級言語を使う意味がなくなります。関数なんて「必要があるから呼ぶ」のだから「スタックが足りなくなるから呼ばない」なんてあり得ないわけですし、自分で書いた関数は気にすることができても標準関数がどう振る舞うかまでは気にしようがありません。 コンパイル時に「十分な量のスタック領域を確保する」以外、対処方法はありません。 ②スタック領域のサイズは「コンパイル時に指定したサイズ」です。 ③8bitCPU時代のアセンブリ言語によるプログラミングにおいては常に気にかけ、時には必要量をシビアに計算する必要がありました。CPU自身が使う分やOS等が割り込み処理で消費する分も考えなければいけなかったので物凄く気を使う部分でした。 が、広大な仮想メモリ空間とメモリ保護機構を持つ現在のコンピュータでそんなこと気にしても仕方ないです。 ④変数なんてlong long intやdouble floatでも8バイト、ポインタだって多くの処理系で8バイトです。100個宣言したってたかが知れてますし、そもそも100個宣言したって人間側の管理能力が追い付きません。 アホみたいに大きな配列をローカルで宣言しなければ問題になることなどほぼありません。 ⑤そもそもスタックは「CPUがプログラムを実行する」という当たり前のことでも消費されるものですから、アマチュアレベルの話であれば「気にしても仕方ない」というスタンスでプログラミングを楽しみましょう。

(1)私はローカル変数で巨大配列を作らないように心掛けています。それで(バグ等を除けば)スタックオーバーフローを起こしたことはほぼありませんので、これで大丈夫だろうと思います。 再帰呼び出しをすると結構喰いますが、それが問題になるほど深くなるような再帰呼び出しを作ったことがありません。 (2)できません。実行中に自動拡張されることもありますので、そのような取得方法は用意されていません。 スタックサイズは、コンパイラー等の開発環境が指定可能です。指定していなければデフォルト値になります。お使いの開発環境のマニュアル等を確認しましょう。 (3)いいえ、気にしません。一般常識としては、スタックサイズが問題になることはありません。 (4)場合によって異なりますが、汎用的には動的メモリ確保します。面倒臭く且つ再帰呼び出しされないことがはっきりしている場合には、静的変数にする場合も少なくありません。 (5)一般常識としては、スタックサイズが問題になることはありません。問題になるような組み方をしているようでしたら、意図的にあまり一般的ではないマイナーな組み方をしているか、無自覚に非常識な組み方をしているか、のいづれかになります。スタックサイズについて勉強することは良いことですが、設計や組み方に関して再考することも重要だと思います。

スタックサイズについては、通常の呼出しでは、ほとんど問題にならないはずです。ローカル変数10個(64バイト)程度では、余程メモリサイズの小さいシステムでなければ、影響ない筈です。 他の解答者の解答にあるように、呼出しごとに領域が確保されるので、再帰呼出しでは問題になることもあります。 巨大配列を宣言していませんか?mallocなどでも、スタックに領域が確保される場合があります。 他には、引数で巨大なデータを渡すと、それがスタックに積まれる場合(コンパイラ)があります。これに対しては、データ丸ごとを引数にするのではなく、アドレス渡し(参照渡し)にすると解決する場合があります。

まぁ簡単に言えばローカル変数の宣言でオーバーフローするような事はまずない。そのくらいの余裕はあります。 問題になるのは再帰呼び出しで何十、何百とネストが深まったよう場合だけです。 なので、実際にオーバーフローしたら考える。 > 10個(64バイト) この程度でオーバーフローはちょっと考えられないけど、例えばマイコンとか? もしくは再帰を失敗したとか? スタックサイズはコンパイラによって変わるし、必要ならコンパイルオプションで設定できます。スタックサイズ変更とかでググれば出てくると思いますよ。

環境(=OS?)に依存する(もしかしたらLinuxはデストリで違うかも) windows11 なら凡そ2Mbyte(1000*1000*2) ・・・ 1Mbyte近くなったら検討を Linuxなら凡そ8Mbyte(1000*1000*8) ・・・ 4Mbyte近くなったら検討を ★3桁Kbyteとか「?」ってなって電卓叩いて概算求めてます。 対策は・・・、 まあ、質問者さんの通り。 再帰呼出し時の工夫: 一例ですが、マージソートのようなスタック配列変数を使用するような場合は、大元(=呼出し元)で領域確保して、使い回したりします。

以下の様な簡易プログラムをデバッガで実行すれば溢れると「例外」が発生します。 #include <stdio.h> #define SIZE (int)(1000*1000*2) int main(void){     char buf[SIZE];     printf("%d %d\n",SIZE); fflush(stdout);     for(int i=0; i<SIZE; i++) buf[i] = i; }