C++03 での同時実行のメモリ モデルは何ですか?
(そして、C++11 は並行性をより適切にサポートするためにメモリ モデルを変更しますか?)
C++03 での同時実行のメモリ モデルは何ですか?
(そして、C++11 は並行性をより適切にサポートするためにメモリ モデルを変更しますか?)
C ++メモリモデルは、C++コードに関して物理メモリが読み取り/書き込みされるタイミングと理由の仕様です。
次のC++標準まで、C++メモリモデルはCと同じです。C++0x標準には、マルチスレッド用の適切なメモリモデルが含まれていると予想され(ここを参照)、おそらく次のリビジョンの一部になるでしょう。 C標準のC1X。現在のものは初歩的です:
したがって、現在の状態は次のとおりです。C++メモリ操作は、メインスレッドで1つのプロセスがあり、変数の読み取り/書き込みの特定の順序に依存するコードを記述しない場合にのみ指定されます。それだけです。本質的に、これは、従来のhelloworldプログラムとは別にあなたが困惑していることを意味します。
もちろん、「今日は私のマシンで動作しますが、正しくない可能性があります」と追加するように求められます。正しい文は、「今日の私のマシンでは、ハードウェア、オペレーティングシステム(スレッドライブラリ)、コンパイラのこの特定の組み合わせで動作し、ある程度は機能しているが、おそらくある時点で機能しなくなるものを実装するのに十分な知識を持っています」です。
わかりました、これは少し厳しいですが、地獄です。ハーブサッターでさえ(イントロを読んでください)、最もユビキタスなC /C++ツールチェーンの1つである2007年以前のすべてのバージョンについて話していることを認めています...
C ++標準委員会は、Javaのメモリモデルよりも制約が少ない(したがってパフォーマンスが優れている)一方で、これらすべての問題に対処するものを考え出そうとします。
Hans Boehmは、この問題に関する論文へのいくつかの指針を、学術的およびC++委員会から収集しました。
他のいくつかの答えを見ると、多くのC ++プログラマーは、あなたが求めている「メモリモデル」が何を意味するのかさえ知らないようです。
質問は、ある意味でメモリモデルに関するものです。書き込み/読み取りの並べ替え(コンパイラ側またはランタイム側で発生する可能性があります)について、(もしあれば)どのような保証がありますか?この質問はマルチスレッドプログラミングにとって非常に重要です。そのようなルールがないと正しいマルチスレッドプログラムを作成することはできません。また、現在の明示的なメモリモデルの欠如により、多くのマルチスレッドプログラムは多かれ少なかれ「運が良ければ」動作します。コンパイラーは、関数呼び出し間でポインターのエイリアスを想定しています。-スレッドをライブラリとして実装できないを参照してください
現在のC++には、標準のメモリモデルはありません。一部のコンパイラは揮発性変数のメモリモデルを定義しますが、これは非標準です。C ++ 0xは、この目的のために新しい「アトミック」プリミティブを定義します。最近のステータスを確認するための徹底的な開始点は、C++のスレッドとメモリモデルにあります。
重要なリンクは、同時実行メモリモデル、アトミックタイプ、およびC ++データ依存関係の順序付け:アトミックおよびメモリモデルの標準的な提案でもあります。
残念ながら、C ++には、Javaのような「標準メモリモデル」はありません。実際の実装は、コンパイラ、ランタイムライブラリ、およびプロセッサに任されています。
したがって、C ++メモリモデル==モデルの混沌とした混合マッシュ。つまり、特定のメモリモデルに依存しない安全なコードを常に作成する必要があります。これは、コンパイラが実行できるため、スレッドプログラミングにも当てはまります。重要なセクションの外で、たとえ順序が狂っていても、最適化したいものは何でも!
共有メモリの一貫性モデルをより深く理解したい場合は、次のチュートリアルを参照してください。
短い答え: 何もありません
長い答え: C++ にはマネージ メモリがありません。自分で割り当てて解放する必要があります。スマート ポインター クラスを使用すると、この負担が軽減されます。割り当てたメモリを解放するのを忘れると、メモリ リークとバグになります。メモリを解放した後に使用しようとしたり、メモリを複数回解放しようとしたりする場合も、厄介なバグです。
低レベルの詳細については、C++ はそれを指定していません。それはハードウェア次第です。メモリーは、ある種のメモリー・アドレスを含むポインターを介してアクセスされます。メモリ アドレスは、物理アドレスまたは仮想アドレスのいずれかです。オペレーティング システム カーネルで作業している場合、またはリアル モードで実行される古い DOS コードを読んでいる場合にのみ、物理アドレスが表示されます。詳細については、仮想メモリを読んでください。優れたリソースがたくさんあります。
x86 アーキテクチャでは、セグメント記述子を使用してメモリをアドレス指定することもできます。これはまったく別のワームであり、Win16 の時代から実際には使用されていません。運が良ければ、対処する必要はありません。
一言で言えば、C++メモリモデルは...
下向きに成長するスタック-つまり、スタックフレームをプッシュすると、スタックポインタの値が以前よりも小さくなります
上向きに成長するヒープ、つまり新しく割り当てられたメモリの終了アドレスは、メモリの前よりも大きくなります。malloc()またはnewを使用して、ヒープにメモリを割り当てます。ヒープに使用可能なメモリが十分にない場合、malloc(またはnew)はシステム関数brk()sbrk()を呼び出して、ヒープのサイズを増やします。brk()またはsbrk()の呼び出しが失敗した場合、mallocまたはnewはメモリ不足の例外で失敗します。
スタックまたはヒープが成長するか増加するかを気にする必要はありません。一部のシステムでは、これらが逆に動作する場合があります。スタックとヒープがアドレス空間の端から内側に向かって大きくなることを考えてみてください。
8ビットバイトでメモリを割り当てるメモリアロケータ、malloc。Newもメモリを割り当てますが、割り当てるメモリの量は、新しくなるオブジェクトのサイズに基づいています。
実行可能コードを含むテキストスペース。テキストはヒープの下にあります。実行中にテキストスペースを変更することはできません
プログラムには、テキストの下に他の特別な目的のセクションがある場合があります。
Linuxシステムでobjdumpを使用すると、プログラムが静的に(ロードされる前に)どのように編成されているかを確認できます。
質問では言及していませんが、「並行性」がこの質問に割り当てたキーワードの1つであることに気付きました。スレッドシステムは、各スレッドのヒープに追加のスレッドスペースを割り当て、スタックポインタを管理してスレッドを切り替えます。
詳細はもっとたくさんあり、その多くは特定のハードウェア、OS、またはスレッドシステムに固有のものですが、それは本質的なアイデアです。