スタックオーバーフローとは
スタックオーバーフローとは、スタック領域の使用量が上限を超えてしまう状態のことです。
関数呼び出しのたびにスタックフレームが積まれていきますが、
その積み重ねが限界を超えると、正常な動作ができなくなります。
初心者さんスタックってあふれるんですか?



そう。容量が決まっているから、使いすぎるとあふれるんだ
スタック領域についてはこちらの記事で解説しています。


メモリ領域解説シリーズ
本記事は「メモリ領域解説」シリーズの1つです。
メモリ領域解説シリーズの全体像はこちら


スタック領域を含むメモリ領域の全体像についてはこちらの記事で解説しています。


なぜスタックオーバーフローが起きるのか
主な原因は次の通りです。
- 無限再帰
- 深すぎる再帰
- ローカル変数の使いすぎ
- スタックサイズの不足
原因① 無限再帰
終了条件がない再帰関数は、スタックフレームが増え続けます。
void func() {
func();
}この場合、関数が呼ばれ続けてスタックがあふれます。
スタックフレームについてはこちらの記事で解説しています。


原因② 深すぎる再帰
終了条件があっても、呼び出し回数が多すぎるとスタックを圧迫します。
int factorial(int n) {
if (n == 0) return 1;
return n * factorial(n - 1);
}n が大きいと、スタックフレームが大量に積まれます。
原因③ ローカル変数の使いすぎ
スタックは関数のローカル変数も保存します。
void func() {
int buffer[10000];
}このように大きな配列をローカルで確保すると、一気にスタックを消費します。



配列ってそんなに危ないんですか?



スタックに置くと一発で容量を食うから注意だね
配列のメモリの関係についてはこちらの記事で解説しています。


スタックオーバーフローが起きるとどうなるか
環境によって挙動は異なりますが、一般的には次のような問題が発生します。
- プログラムがクラッシュする
- 不正なメモリアクセスが発生する
- 意図しない動作になる
組み込み開発では、リセットやフリーズの原因になることもあります。
組み込み開発で特に注意すべき理由
組み込み環境では、スタックサイズが非常に小さいことがあります。
- 数KB〜数十KB程度
- 固定サイズで変更できない場合もある
そのため、PCでは問題ないコードでも、組み込みでは簡単にスタックオーバーフローが発生します。
スタックオーバーフローの対策
① 再帰を避ける / 制限する
ループに置き換えられる場合は、再帰を使わない方が安全です。
② ローカル変数を減らす
大きな配列はスタックではなく、別の領域を使うことを検討します。
- 静的領域(data / bss)
- ヒープ(malloc)
静的領域についてはこちらの記事で解説しています。


ヒープ領域についてはこちらの記事で解説しています。


一方で組み込み開発ではヒープ領域の使用にも注意が必要です。
詳しくはこちらの記事で解説しています。


③ スタックサイズを確認する
組み込みでは、リンカスクリプトや設定でスタックサイズが決まっています。
メモリマップも使用して確認する必要があります。
- スタックサイズの確認
- 使用量の見積もり
は非常に重要です。
メモリマップについてはこちらの記事で解説しています。


またリンカスクリプトについてはこちらの記事で解説しています。


スタックフレームとの関係
スタックオーバーフローは、スタックフレームが積み重なりすぎることで発生します。
関数呼び出し1回ごとにスタックフレームが作られるため、
- 再帰
- 関数のネスト
が深くなるほど危険になります。
スタックフレームの仕組みはこちら


まとめ
- スタックオーバーフローはスタック容量超過で発生する
- 主な原因は再帰とローカル変数
- 組み込みでは特に発生しやすい
- 対策として設計段階から意識することが重要
この記事が参考になった方へ
メモリ領域については他の記事でも解説しています。


またスタック領域の配置にかかわるC言語の文法についても当サイトでは解説しています。


技術に関するご相談・開発・自動化ツール作成・記事執筆などのご依頼も承っています。
小さなご相談からでもお気軽にご連絡ください。









コメント