読者です 読者をやめる 読者になる 読者になる

Gen's blog

CTFとか、競プロとか、その他諸々

スタックとメモリ解放の話

C

Twitterで、とあるコードについて話題になっていたので、まとめてみる。

問題のコード

#include <stdio.h>

int* func(){
    int a = 114514;
    return &a;
}

int main(){
    printf("%d\n", *func());
}

結論としては、動作は未定義である。環境によって挙動が変わる。 ということらしいが、実際にはどのような挙動をする可能性があるのだろうか。

様々な挙動

  1. 114514と表示される
    私が普段使用している環境だと、この挙動を示した。 「局所変数aの領域がページアウトされていない」かつ、「printf()の呼び出しの際、引数や局所変数で上書きされていない」場合にこの挙動を示す。

  2. Segmentation fault
    wandbox(C++コンパイラ)で確認した挙動。 局所変数aがページアウトされていた」場合にこの挙動を示す。 コンパイラがnull返すようにしてくれていたようです。Thanks, うさぎさん

  3. 別の値が表示される
    printf()呼び出しの際に、引数や局所変数で上書きされた」場合に起こりうる。 未確認。

追記:gcc 4.9以前と5.1以降で変わるらしい。5.1以降だとnullを返すようになる。 d.hatena.ne.jp

感想的な

そもそも、CとかC++はコードの安全面はプログラマに任せているというような話を聞いた気がするし、 こんなコード書くなという話なんだけれど…

こういった、未定義のコードの挙動について考えてみるのって楽しい。もっと探ってみたい。