8

ある時点では、静的初期化時に実行されるスレッド処理を行うためにコンパイラが特別なコードを挿入するため、main()の最初の行までスレッドを安全に作成できないことを覚えています。したがって、構築時にスレッドを作成するグローバルオブジェクトがあると、プログラムがクラッシュする可能性があります。しかし今、私は元の記事を見つけることができません、そして、私は、これがどれほど強い制限であるのが好奇妙ですか?それは標準によって厳密に真実ですか?ほとんどのコンパイラに当てはまりますか?それは本当ですか? をスタティック初期化そのものにすることは可能ですか?マルチスレッド? (例えば、2つのグローバルオブジェクトが互いに接触しないことを検出し、プログラムの起動を加速するためにそれらを別々のスレッドで初期化する)スタティック初期化中にスレッドを安全に作成できますか?

編集:明確にするために、実装が本当に大きく異なっているかこの点で、あるいはそれが疑似標準であるかどうかを判断する必要があります。たとえば、技術的には、異なるアクセス指定子(public/protected/etc)に属するメンバーのレイアウトをシャッフルすることが技術的に可能です。しかし、私が知っているコンパイラは実際にはこれを行いません。

+0

"標準で厳密に真です" - C++ 03標準ではスレッドの主題について何も言及していません。現在の動作に関する限り、POSIX(*標準*、*標準)、MSDN、Boost、またはその他のコンパイラ、プラットフォーム、スレッドAPI用の実装固有のドキュメントがあります。つかいます。 –

答えて

6

厳密には言語ではなく、Cランタイムライブラリ(CRT)です。
ウィンドウにCreateThread()などのネイティブコールを使用してスレッドを作成すると、CRTの介入なしにOSに直接進むため、好きな場所で実行できます。
もう1つのオプションは、CRTの一部である_beginthread()を使用することです。スレッドセーフのerrnoを持つなど、_beginthread()を使用することにはいくつかの利点があります。 Read more about this here_beginthread()を使用してスレッドを作成する場合は、_beginthread()に必要な初期化が行われていない可能性があるため、問題が発生する可能性があります。

これは、正確にはmain()の前に何が起こり、どのような順序で発生するのかという、より一般的な問題に触れています。基本的には、Visual Studioでmain()より前に起こる必要があるすべてのものを処理するプログラムのエントリーポイント機能を持っています。実際にCRTにあるこのコードを見て、正確に何が起こっているのかを調べることができます。そのコードに到達する最も簡単な方法は、コード内のブレークポイントを停止してから、前にスタックフレームを確認することです。main()

+0

ありがとう、これは、MSVCでWindows上の状況がどのようなものか、いくつか考えています。私はまだ他のプラットフォームについては興味がありますが、Windowsで安全かどうかは実際には答えていません(_beginthread()は実際にはまだ初期化されていない可能性がありますか?)。 –

+0

私はこれも知ってほしかったです。ドキュメントには言及していないようです。 – shoosh

2

DllMainで実行できる操作と実行できない操作は、Windowsの制限です。特に、DllMainでスレッドを作成するはずがありません。静的初期化は、DllMainから頻繁に発生します。次に、静的初期化中にスレッドを作成できないことは論理的にはわかります。

+1

注: 'プロセス起動とDLL初期化ルーチン中に、新しいスレッドを作成することはできますが、http://msdn.microsoft.comからプロセスのDLL初期化が完了するまで実行されません。com/ja-us/library/ms682453%28v = VS.85%29.aspx –

+0

公正なポイントは、それを見ていませんでした。コメントは 'CreateThread'に特に適用されますが、' _beginthreadex'にはこの例外はありません。 – MSalters

0

C++ 0x/1xのドラフトを読んでいる限り、main()より前のスレッドを開始するのは問題ありませんが、静的初期化の通常の落とし穴の影響を受けます。準拠している実装では、静的コンストラクタやスレッドコンストラクタの前に、スレッドを初期化するコードを実行する必要があります。

関連する問題