1

return EXIT_SUCCESS;frommain()と どこからでも呼び出すの違いexit(EXIT_SUCCESS)を調べてみましたが、これまでに見つけた最高のリソースはSO のこの回答です。ただし、明確にしたい詳細が 1 つあります。

私にとって最も説得力のある反対意見はexit()(その投稿で述べられているように)、ローカル スコープのオブジェクトに対してはデストラクタが呼び出されないということです。しかし、これは他のオブジェクトにとって何を意味するのでしょうか? exit()メソッドからスタック上でかなり離れた別の場所から呼び出しmain()ているが、その呼び出しのみを含み、変数を含まないブロック (メソッドであっても) 内にある場合はどうなりますか? スタックの他の場所にあるオブジェクトは引き続き破棄されますか?

私のユースケースはこれです:

「終了」コマンドが与えられるまでユーザーに入力を求めるアプリケーションがあります (テキストベースのアドベンチャー ゲーム)。これを実現する最も簡単な方法は、単に を呼び出すメソッドに「quit」をマップすることでしたexit(EXIT_SUCCESS)。もちろん、ユーザーが実行できるすべてのアクションが、ゲームを続行するかどうかを示すブール値を返し、return false終了したいときにだけ返すように書くこともできますが、これ以外で何かを返すのtrueはこれだけですmethod -return true回避したいという理由だけで、他のすべてのアクション メソッドが必要になりexit()ます。一方、私は非常に多くのオブジェクトを作成し、非常に多くのメモリを動的に割り当てます。これらはすべて、クラス デストラクタによって処理される必要があるため、それらが実行されることが重要です。

ここでのベストプラクティスは何ですか? これは の良いケースですか、それともメソッドexit()と同じくらい悪いケースですか?main

4

3 に答える 3

3
if (command == "quit") {
    throw QuitGameException();
}

例外をスローできます。例外は安全にスタックをアンワインドし、途中ですべての呼び出し元のオブジェクトを破棄します。

于 2013-01-08T21:42:48.020 に答える
1

私はそれが何を言っているのか知っているので、そのSOの投稿を読むつもりさえありません。exit()を使用しないでください。

私は exit() を使用する 1 つの理由を知っています - とにかく完全に運命づけられていて、うまく終了する方法がない場合。このような場合、コード 0 で終了することはありません。したがって、とにかくクラッシュしようとしているときは、0 以外の exit() を使用してください。

それ以外の場合は、すべてのメモリをクリーンアップするために、メイン ループを離れてメイン プロセスを正常に終了できるようにする変数を作成します。このようなコードを書かないと、たとえばメモリ リークをすべて検出することはできません。

于 2013-01-08T21:45:09.670 に答える
1

スタックの他の場所にあるオブジェクトは引き続き破棄されますか?

いいえ、exit() は次のことを (順番に) 行います。

  • スレッド ストレージ期間を持つ現在のスレッドに関連付けられているオブジェクトは破棄されます (C++11 のみ)。
  • 静的ストレージ期間を持つオブジェクトは破棄され (C++)、atexit に登録された関数が呼び出されます (未処理の例外がスローされた場合は、terminate が呼び出されます)。
  • すべての C ストリーム ( の関数で開く) が閉じられ (バッファリングされている場合はフラッシュされ)、tmpfile で作成されたすべてのファイルが削除されます。
  • 制御がホスト環境に戻されます

から: http://www.cplusplus.com/reference/cstdlib/exit/

exit() はスタックをアンワインドせず、スタック全体のメモリを解放するだけで、スタック内の個々のオブジェクトのデストラクタは実行されません。exit() の使用は、単純なデストラクタ (外部リソースを扱わないオブジェクト) を持たないすべてのオブジェクトが静的ストレージ (つまり、グローバル変数またはローカル スコープの静的変数) に割り当てられている場合にのみ安全です。ほとんどのプログラムには、ファイル ハンドラー、ソケット接続、データベース ハンドラーなどがあります。動的に割り当てられたオブジェクト (外部リソースを処理しないオブジェクト) は、プログラムがとにかく終了しようとしているため、必ずしも割り当てを解除する必要がないことに注意してください。

exit() は C から継承された機能であり、デストラクタがないため、外部リソースのクリーンアップは常に atexit() を使用して調整できます。一般に、C++ で exit() を安全に使用することは非常に困難です。代わりに、C++ ではプログラムを RAII で記述し、例外をスローして終了し、クリーンアップを行う必要があります。

于 2013-01-08T22:12:04.057 に答える