4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

safe Rust でスタックオーバーフローする方法

Posted at

safe Rust は安全な言語と言われますが, 残念ながらスタックオーバーフローをコンパイル時に検出し防ぐことはできません. あるコードがスタックオーバーフローを起こすかどうかは環境に依存する話なので当然といえば当然ですが.

大きなデータを持つ

スタックサイズは OS 等にもよりますが数 MB 程度なので, それより大きな array をスタックに確保しようとすれば一発でオーバーフローします.

fn main() {
    let _ = [ 0f64; 4_000_000 ];
}

解決策: 大きなデータはヒープに持つようにする.

関数の再帰呼び出し

スタックオーバーフローの一番多いと思われるパターンは関数の再帰呼び出しです. が, rustc は関数の再帰呼び出しが終了しないことに気づくと警告を出してくれます.

fn main() {
    fn tmp() -> i32 { tmp() }

    tmp();
}

これをコンパイルすると function cannot return without recursing というメッセージとともに警告が表示されます. が, コンパイル自体は成功してバイナリを実行するとスタックオーバーフローします.

ただ, これよりちょっとだけ複雑な再帰呼び出しではコンパイラが気づかないこともあります.

fn main() {
    fn a() -> i32 { b() }
    fn b() -> i32 { a() }

    a();
}

また, 再帰は理論上終了するものの, 終了するまでに必要な関数の呼び出し回数が多すぎるためスタックオーバーフローする, というケースもあります. これは末尾最適化により解決する可能性があります.

解決策: 設計ミスなので見直す. または末尾再帰最適化をする.

参考文献

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?