情報構造論の前期期末試験で、局所変数返しの解答が多かったので、メモ。
JavaScript でプログラムを書いていると、動くネタだけど、C言語では初心者がよく間違って書いてしまう定番であり、それなりに動いたりするから、誤解が増えてしまう可能性もある。
スタック変数返し
char* foo() { char str[ 20 ] ; strcpy( str , "Hello World" ) ; return str ; } char* bar() { char baz[ 20 ] ; memset( baz , 'A' , sizeof( baz ) ) ; return NULL ; } void main() { char* ans = foo() ; printf( "%s¥n" , ans ) ; // Hello World // 一見正しく動いているように思うかも。 bar() ; // 局所変数を触るだけの処理 printf( "%s¥n" , ans ) ; // AAAAAAAAAAA // ans の中身が壊れている。 }
静的局所変数返し
上記のスタック変数を返す問題点を示すと、じゃあ静的局所変数でいいじゃん….という話がでてくる。
char* foo() { static char str[20] ; strcpy( str , "Hello World" ) ; return str ; }
この方式なら、スタック領域ではなく静的変数領域なので、関数呼び出しで破壊されることはない。
しかし、この方式は「スレッドセーフ」ではない。foo() の処理後に、スレッドを起動した場合、スレッドではメモリ空間が共有されるため、foo() を保持していて、別スレッドがそのメモリを書き換えると、他方は中身が変わってしまう。
(参考「スレッドセーフではないCライブラリ関数」)