スタックに確保した変数の有効範囲に気をつけるおおたの物置スタックに確保した変数の有効範囲に気をつける2014-09-16cppTweetC++にはスタックとヒープという、使い方の違うメモリ領域が存在します。rubyとかjavaではこのような違いは基本的に意識する必要が無いため、間違った使い方をしてしまう場合があります。普通の変数はスタックに積まれるため、スコープを抜けるとたとえ使っていても破棄されます。以下に、関数の中で文字バッファをスタックに確保し、その参照を戻す関数の間違った例を上げます。0;}環境によりますが、おそらく二回目のtest_filenameの出力がおかしくなると思います。私の場合は以下のように、test_filenameにexample_filenameの内容が書き込まれていました。test.txtexample.txtexample.txtgetTextFilename内のstrはスタックに確保されるので、関数終了時に解放されます。そのため、戻り値の指し示す文字列は解放済みメモリとなり、勝手に変更される可能性があります。上の例ではたまたま同じアドレスが再利用されたため、同じ文字列が設定されました。間に様々な処理を実行した場合は、謎の値が書き込まれるなどがあり得るため注意が必要です。対策このような場合、いくつかの対策があります。引数で渡す1つ目が、strncpyやstrncatのように、メモリ利用域を引数として受け取る方法です。これにより、自分のスコープから外れても値を保持することができます。先ほどの例ですと、main側でcharの配列を確保して関数の引数でそれを受け取るといった形です。確保したスコープを抜けるとやはり解放されますが、確実に解放されるためとても楽です。ヒープに確保する2つ目はmallocやnewでヒープ領域に確保する方法です。以下はnewで配列を確保するように書き換えました。0;}newやmallocでメモリ領域を確保した場合、ヒープ領域に確保され、スコープを超えてメモリを確保し続けられます。明示的に解放しないとメモリリークが起きるため、注意が必要です。オブジェクトをコピーする3つめがコピーを使う方法です。今回の関数では配列を使っていますが、コピーコンストラクタをもつstd::stringを使うと、スタック上の内容を関数の外に安全にコピー出来ます。0;}関数の戻り値は戻り先にコピーされるまでは保持されるという仕様があるらしく、コピー可能なものに関しては戻り値としてちゃんと返すことが出来ます。0の0も変更される可能性が出てきてしまうため、当然の仕様と言えます)ただし、コピー処理が走るため、オブジェクトが巨大な場合、メモリ消費が増えたり、時間がかかる可能性があるので注意が必要です。スタックで確保した場合、解放忘れ等がないためとても簡単ですが、スコープから抜けると解放されてしまうため、有効範囲を考えないといけません。今回は文字列で例を挙げましたが、自作クラスなどでもほぼ同じ事がいえます。中途半端にコピーされ、ß予期せぬエラーに繋がります。ota42yC++/Ruby/RoR/golang/rust/flutter。