2013-04-15 8 views
15

私はオペレータdeleteへの呼び出しが同期かどうか疑問に思っていました。私は言い換えれば、:演算子 'delete'への呼び出しは同期していますか?

delete p; 

は、C++標準では、このコールの実行が終了した後にのみメモリが解放されることを保証していますか?あるいは、非同期的な呼び出しで、これが最適な時期になるとすぐにOSがこのメモリを解放するためのタスクをスケジュールするだけですか?

最初のケースが有効な場合は、独自の非同期削除機能を実装する必要があることを意味しますか?メモリが完全に解放されたときに私たち(プログラマ)が気にしない時間がほとんどだと言うので、私たちのコードがフリーズしてこれを待つことは望ましくありません。むしろ削除のためにタスクをスケジューリングし、直ちに実行を続行します。 C++は標準的な機能を提供していますか?

+0

"メモリが解放されました"を定義してください –

+0

リリース時に定義する場合は、独自の 'new'と' delete'演算子を使用してください。小さなオブジェクトがたくさんあるときは非常に一般的です。 – Naszta

+0

メモリを解放することは、それを割り当てることよりもはるかに安い –

答えて

15

deleteは同期です。さて、これは基本的なメモリがオペレーティングシステムによって実際にその時点で解放されているのではなく、C++システムの視点から見れば、あたかもあたかもあたかも同じように動作することを意味します。

私はそれがだ、ほとんどの時間は、私たち(プログラマが)、メモリが解放されたときに正確に

しかしdeleteがメモリについて主にない気にしないことを言うと思いますので、私は聞いていますのよ決定論的な方法でデストラクタを呼び出すことと同じように、メモリに限らず汎用的なリソース解放機構です。ここではであり、それ以外の場合はC++のコア側面の1つ - RAII - は動作しません。

+0

私はあなたの説明が好きです、それは間違いなく理にかなっています。 +1。 –

+0

私はOPが念頭に置いている(非同期I/Oのような)意味で、 "非同期性"についてのC++標準に何か*があるとは思わない。 (スレッディングとメモリモデルについての唯一のものがあります)だから、コンセプト全体が決して定義されていないとき、「Xは同期している」と言いたいとは思わなかった。 –

+0

@KerrekSBそれは良い点だ。それらが定義されていないフィールドで非同期セマンティクスについて話すのは難しいです。 –

4

あなたが懸念している限り、すべてはあなたが期待しているとおり正確に動作し、隠されたトラップや邪魔者はありません。あなたはいつもT * p = new T; delete p;と言うことができますが、これはどんな文脈で起こっても問題ありません。

オペレーティングシステムがすべての種類のプロセスとスレッドに同時にメモリを割り当てる必要がある場合、その問題は既に正しく解決されているとみなすことができます。

より正式に、18.6.1.4/1は(「データレース」)は言う:データ競合、operator newのライブラリバージョン、グローバルoperator newのユーザー交換バージョンの有無を決定する目的のために

、およびC標準ライブラリ関数callocmallocは、あたかも戻り値によって参照される記憶域にのみアクセスして変更したかのように動作します。 のoperator delete、ユーザー置換バージョンoperator delete、およびC標準ライブラリ関数freeは、最初の引数で参照される記憶域にのみアクセスして変更したかのように動作します。

「ブロック性」について:これは、Cライブラリの割り当て関数の機能にまで及んでいます。 「この関数はあるメモリへのポインタを返す」以外に何も指定されていません。それはどのようにメモリ割り当てを提供するかは、プラットフォームに依存します。

+0

私は彼が、スレッドセーフであるかどうかとは対照的に、 'delete'への呼び出しがブロックしているかどうかを尋ねていると思います。 –

+0

はい、ブロックされているかどうかは興味があります。 –

+0

@AndrewDurward:少なくとも「ブロックする」という意味を明確にするまでは、質問内では答えられないと思います。シングルスレッドのMS-DOSでは、答えは「いいえ」でもよいですが、マルチタスクシステムでは、いつでもデスケジューリングできます。 –

0

C/C++でのフリーコールは、何があっても非常に高速です。 その点でより適切な時期に削除を遅らせる理由はありません。 その目的のために行う必要のある本は、実際の無料通話時間を相殺する以上のものです。

デストラクタがDB接続のソケットを閉じるのと同じように動作する場合は、後でそのタイプの作業を行うことができますが、これは例外的なケースです。

+1

それはとても素朴です。 'std :: vector * pv = new std :: vector(1000000);'を考えると、このコードはナンセンスなので無視してください。 'delete pv;'を呼び出すことは、コンテナ内のすべてのオブジェクトのデストラクタを呼び出す必要があり、その実行を遅延させる非常に良い理由があるため、非常に非効率的です。 –

+0

ええと、マルチコアマシンでその目的のためだけに2番目のスレッドで削除を実行できると思います.... –

7

delete p;がメモリをOSに戻すことは保証されません。実際、かなり(ほとんどの)実装では、何の処理もしません。

あなたがdeleteを呼び出すときにどのくらいが起こるんが変わる - いくつかのケースでは、ほぼ瞬時です(ちょうど空きメモリブロックのリストにブロックをリンク)。他のものでは、オブジェクトを破棄し、おそらく解放されているブロックと合体できる隣接ブロックの現在の空きリストを検索するなど、もっと多くの作業を行います。

関連する問題