ぼく用あれこれまとめ
C++の強制終了について。
最終更新:
bokuyo
-
view
C/C++の強制終了について。
std::exit()関数
#include <iostream> void Eureka() { std::cout << 156 << std::endl; std::exit(1); //ここで強制終了 } int main() { Eureka(); std::cout << 256 << std::endl; return 0; }
- exit()関数は、main()文内の「return 0;」と同じことをしてるらしい。(詳しく知らない)
- ちなみにstd::abort()関数っていうのもあるけど、それは使った瞬間プログラムをほんとの意味で強制終了させるから怖い。
- VC++環境でやると、ランタイムエラー並みの扱い。他に手段があるとき以外は、使わないほうがよさそう。
- VC++でstd::abort()使うととてつもなく実行時に怒られるよ。
- std::exit()関数でもいいけど、exit()関数でもいけるっぽい。
std::atexit()関数
#include <iostream> void Eureka() { std::cout << "Seven" << std::endl; } void Renton() { std::cout << "Thurston" << std::endl; } int main() { std::atexit(Eureka); std::atexit(Renton); std::exit(1); std::cout << 156 << std::endl; return 0; }
- std::atexit関数を使って、終了時に行いたい終了処理関数を登録できる。
- atexit関数の引数に渡す関数(実際は関数ポインタ)には条件がある。
- void型
- 引数とらない
- atexit関数の引数に渡す関数(実際は関数ポインタ)には条件がある。
- atexit()関数での登録順とは逆順に終了処理は実行される。(LIFO=後入れ先出し)
- abort()関数で終了したときは終了処理は行われない。
- exitのときは終了処理が行われる。またmain文の「return 0;」時にも同様に行われる。
- ようは、デストラクタと同じ。C++なら例外処理使えば、exitとatexitの代わりになるのでは…?
- atexit関数はC99で定義されているユーティリティ関数。
- C99では少なくとも32個の関数が登録できることを処理系に求めている。
強制終了されたとき、確保されていたメモリはどうなるの?
- いついかなる状況でどのような終了のされ方が行われようとも、知った話ではないとのこと。
- つまりどんな状況であれ、「確保したメモリは解放する」という前提のもとCはできてるのだそうです。(詳しくは知りません)
- 通常newして確保するようなメモリは解放し忘れてもOS側が解放してくれる。
- もちろん、C言語が保証してることじゃなくて、あくまでOS側のサポート。でもだいたい最近の優秀なOSはやってくれるっぽい。
- freeとかって処理系依存らしいよ。
- ある確保したメモリを複数のプログラムで参照してる場合の解放し忘れたときの挙動はちょっと今のぼくには理解できない。
- 複数プログラムでメモリを共有してる場合は注意。
- システムリソースの場合、解放する必要あり。通常のメモリとは違い、こちらは厄介。
- いわゆるメモリリークってコレのこと。ちゃんと解放してあげようね。
- 深刻なシステムリソース不足は悩みの種だよね。
- Windowsでアプリケーション用の(GUIとかに使う)メモリ領域をシステムリソースって呼んでる。
- プログラムの内部に埋め込まず外部から読み込むデータのことをリソースってMSさんは呼んでるけどそれとは別もの。
- じゃあ、強制終了した場合、確保していたメモリを確実に解放してあげる場合どうすればいいの?
- abort()でなければ、デストラクタまたはatexit()とかを使う。
- そもそも、強制終了する時点で、解放がどうのこうのじゃなくね…?その前に強制終了しないようなソースを…。
- 低級言語レベルでOS内部の動きを見ていくなら、どういう動きを行うのか知っておくといいかもね。
- ゲームプログラミングではメモリの扱い方が重要視されるから一度詳しくOS内部の動き見てみたいね。
参考文献
- C/C++セキュアコーディング(Robert C. Seacord 著)