マルチスレッドプログラミング相談室 その6

このエントリーをはてなブックマークに追加
850デフォルトの名無しさん
void in_thread_func() {
 static std::string("あいうえお");
}
も同じだね。

大体、「デストラクタ」と言っているのだから
POD型ではないので、「(大抵の処理系で)実行開始時に確保されてる」等の
Cの話は関係ない。
むしろ、こういうものだと捉えない>>832>>846が不思議。

あ、デストラクタの呼び出し順は、生成と逆順であることが保証されているよ。
実装的には、初期化時はフラグ(大抵排他制御されてない)を使って判定して
内部的にatexitのようなもの登録することで
デストラクタを呼び出しているものが多いみたいね。
851デフォルトの名無しさん:2008/06/22(日) 00:03:36
>>850
> デストラクタの呼び出し順は、生成と逆順であることが保証されているよ

関数内のstaticオブジェクトも?
MAJIDE?
852>>836:2008/06/22(日) 00:13:02
>>847-850
すまん、確かにお前等の言うとおりだった...。

全然勘違いしてた。orz

>>831
> 破棄のタイミングはmain関数より後なんで。

そもそも、main 関数終了後まで生き続けるスレッドなんて言うものを
言語仕様策定時に想定していなかったか、想定しててもそれはプログ
ラマ側の責任だよと言うことなんだろうな。
853>>836:2008/06/22(日) 00:21:38
>>851
> 関数内のstaticオブジェクトも?
> MAJIDE?

マジみたい、

VC++ 2005 でやってみると、コンストラクタを実行する時にデストラクタを
登録している。

>>850 の言う通り初回かどうかの判定は排他制御されてないフラグでやって
るからマルチスレッドだと注意しないとえらいことになりそう。
854デフォルトの名無しさん:2008/06/22(日) 01:24:12
ここ30年前ほど悩んでいるのだけれど、静的変数の初期化ってどうやって排他する
のでしょうか?

void f() {
static class X i; // ←初期化が排他制御されない。
}

これを回避するために

void f() {
X* px;
static Mutex mutex;
{
MutexLock lock(mutex);
static class X i;
px = &i;
}
px->zzz();
}

としたのですが、mutexの初期化が排他制御できないのです。
mutexをメインスレッドに置くぐらいしか思いつきませぬ。
855デフォルトの名無しさん:2008/06/22(日) 01:36:52
mutexを関数の外に出せば、main実行前にメインスレッドで初期化されるね
856デフォルトの名無しさん:2008/06/22(日) 02:17:49
C互換構造体を使う(BinaryHacksより)
って方法はダメ?
857デフォルトの名無しさん:2008/06/22(日) 02:19:08
>>855
static initialization order fiascoが問題になる
858デフォルトの名無しさん:2008/06/22(日) 02:21:16
一般的には、lockを関数の外に出して、コンストラクタで初期化するべき。

何か事情があって、どうしても関数内で行う必要があるとき(例えばDLL内など)は
CASを使ってlockへのポインタを初期化することで、なんとかなる。
オブジェクトが複数確保しても(余剰分はすぐ解放する)コスト等で問題ないなら
オブジェクト自体をCASを使って確保する手もある。