[表示 : 全て 最新50 1-99 101- 201- 301- 401- 501- 601- 701- 801- 901- 1001- 2chのread.cgiへ]
Update time : 06/04 17:21 / Filesize : 278 KB / Number-of Response : 1002
[このスレッドの書き込みを削除する]
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧] [類似スレッド一覧]


↑キャッシュ検索、類似スレ動作を修正しました、ご迷惑をお掛けしました

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



1 名前:デフォルトの名無しさん mailto:sage [2005/11/03(木) 11:23:05 ]
マルチスレッドプログラミングについて語るスレ。
OS・言語・環境は問わないが、それゆえ明記すべし。

その1 pc3.2ch.net/test/read.cgi/tech/997345868/
その2 pc5.2ch.net/test/read.cgi/tech/1037636153/
その3 pc8.2ch.net/test/read.cgi/tech/1098268137/

175 名前:デフォルトの名無しさん mailto:sage [2005/12/28(水) 16:51:48 ]
おバカSunよね〜

176 名前:デフォルトの名無しさん mailto:sage [2006/01/02(月) 08:35:56 ]
くだらない質問ですみませんが
TCPで同じディスクリプタにread()するスレッドとwrite()するスレッドを分けたとき
全二重だから同時にread()とwrite()を実行しても問題ありませんよね?
あと片方が同期無しでclose()するのって問題ありますかね

177 名前:デフォルトの名無しさん mailto:sage [2006/01/02(月) 08:40:05 ]
同時にread/writeしても問題なし。
HTTPサーバのようなものを作ってるなら相手が一方的にclosesocketしたくらいでおかしくなっては困る。


178 名前:デフォルトの名無しさん mailto:sage [2006/01/02(月) 12:25:53 ]
Solaris2.xではデッドロックしてたなあ(遠い目)

179 名前:デフォルトの名無しさん mailto:sage [2006/01/03(火) 03:50:46 ]
x86 とかで int の値を書き込むスレッド(A)と読み込むスレッド(B)がある場合,
更新途中の値が(つまり 32bit 中の 16 bit が新しい値で残りが古いままとか)
B に見えてしまうということはありうるでしょうか?

# long とかだとまずいですよね.

180 名前:デフォルトの名無しさん mailto:sage [2006/01/03(火) 04:40:29 ]
>>179
前スレで延々やってたと思う

そこが本題でなければ、排他で済ませて先行った方がいいと思うヨ

181 名前:デフォルトの名無しさん mailto:sage [2006/01/03(火) 04:56:02 ]
>>180
レスありがとうございます.前スレの読み方がよく分からないので憶測になっ
てしまいますが,前スレの議論では結局「あり得る」という結論に至ったとの
理解で良いでしょうか?

参考になりそうな資料へのポインタを教えて頂けるとうれしいです.

> そこが本題でなければ、排他で済ませて先行った方がいいと思うヨ

性能的な面から可能な限り B に対する排他処理は避けたいと考えています.

182 名前:デフォルトの名無しさん mailto:sage [2006/01/04(水) 15:07:19 ]
>>181
OSに用意されている、Atomicな書き換えAPIを利用すれば宜しかろう。
32ビットバスでアライメントも合っていれば素直にAtomicに書き換わると思うが。

183 名前:デフォルトの名無しさん mailto:sage [2006/01/04(水) 16:15:06 ]
レスありがとうございます。調べてみます.



184 名前:デフォルトの名無しさん [2006/01/13(金) 02:07:27 ]
マルチスレッドプログラミングで注意することを列挙してくれ。

185 名前:デフォルトの名無しさん mailto:sage [2006/01/13(金) 02:19:22 ]
ひとつ!急いで口で吸え!

186 名前:デフォルトの名無しさん mailto:sage [2006/01/18(水) 14:53:41 ]
ふたつ! 不埓な悪行三昧!


187 名前:デフォルトの名無しさん mailto:sage [2006/01/18(水) 16:18:23 ]
みっつ! 想定の範囲内です。

188 名前:デフォルトの名無しさん mailto:sage [2006/01/18(水) 16:55:53 ]
よっつ、読んでも書いちゃダメ


189 名前:デフォルトの名無しさん mailto:sage [2006/01/18(水) 16:56:28 ]
いつつ、いつも心に排他処理


190 名前:デフォルトの名無しさん mailto:sage [2006/01/18(水) 16:59:48 ]
むっつ、無理せずmutex


191 名前:デフォルトの名無しさん mailto:sage [2006/01/18(水) 17:21:48 ]
ななつ、仲良くSemaphoeで共有

192 名前:>>46 mailto:sage [2006/01/18(水) 23:32:09 ]
やっつ、やっぱりここでも排他処理

193 名前:デフォルトの名無しさん mailto:sage [2006/01/19(木) 00:43:25 ]
ここのつ!心を鬼にして排他処理



194 名前:デフォルトの名無しさん mailto:sage [2006/01/19(木) 01:03:03 ]
糞スレ立てんな

195 名前:デフォルトの名無しさん mailto:sage [2006/01/19(木) 01:39:58 ]
とう、でとうとう割り込まれた。

排他だけじゃなく、割り込み禁止も忘れないでね☆

196 名前:デフォルトの名無しさん mailto:sage [2006/01/21(土) 01:53:34 ]
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)で作ったイベントに対して
SetEvent(hEvent);←TRUEがかえる
でも、その次に
WaitForSingleObject(hEvent, 0)とやってもWAIT_OBJECT_TIMEOUTがかえる。
こういうことがおきているのですがどのようなことが考えられますか?




197 名前:デフォルトの名無しさん mailto:sage [2006/01/21(土) 07:15:10 ]
>>196
SetEventは成功したけど、イベントオブジェクトがシグナル状態になる前にWaitForSingleObjectがタイムアウトした。

198 名前:>>46 mailto:sage [2006/01/21(土) 09:16:54 ]
>>196
他のスレッドが一生懸命 ResetEvent(hEvent) を
やってる。

199 名前:196 [2006/01/21(土) 14:20:25 ]
>>197
SetEventってシグナル状態にした後で戻るわけではないのですか?

>>198
ソースを見る限りほかのスレッドが触ることはなさそうなのですが確信持てないです。
SetEventとWaitForSingleObjectの間で他のスレッドにスイッチしなければそういうことはおきないですよね?
であれば確認のためにはスレッドのスイッチをSetEventとWaitForの間で抑制してあげればいいですよね。
なにか、任意のコードブロックではスレッドスイッチを禁止する方法はないでしょうか


200 名前:デフォルトの名無しさん mailto:sage [2006/01/21(土) 14:26:18 ]
ちょっと確認だが、WaitForSingleObject()の第二パラメータの0ってNoWaitだよな?
単に待てば委員で内科医?

201 名前:デフォルトの名無しさん mailto:sage [2006/01/21(土) 14:42:02 ]
>196のままのコードを実行してみたけど、ちゃんと0が帰ってきたよ。

202 名前:デフォルトの名無しさん mailto:sage [2006/01/21(土) 15:04:56 ]
>>199
>>196の事象が事実であるなら、そういうものだと思って使うべき。
嫌なら別の手段を用いるべき。

203 名前:196 mailto:sage [2006/01/21(土) 15:47:24 ]
>>200
SetEventしてそれが本当にシグナルになったかを見るためにWaifFor・・したのですが、
それがなぜかシグナルになっていないのです。

>>201
検証ありがとうございます。>>196のままのコードだとそうなると思いますが、実際にはほかのスレッドもいるので
何が起きているかはよくわかっていません。(デバッガでステップ実行したりデバッグライトを入れるだけで動きが変わるため)


とりあえず、月曜にほかのスレッドがResetしていないか確認したいと思います

あとSetEventって非同期に動いたりしませんよね?
SetEvent(hEvent);
ここで誰かがResetEventしない限り下はTRUEにならないですよね?
if(WaitForSingleObject(hEvent,0)==WAIT_OBJECT_TIMEOUT)
{
}




204 名前:デフォルトの名無しさん mailto:sage [2006/01/21(土) 17:01:11 ]
>>203
だから、WaitForSingleObject(hEvent, INFINITE)してみたら?

205 名前:デフォルトの名無しさん mailto:sage [2006/01/21(土) 21:15:12 ]
そもそも、WAIT_OBJECT_TIMEOUTってなんだ?

成功:WAIT_OBJECT_0 or WAIT_TIMEOUT or WAIT_ABANDONED
失敗:WAIT_FAILED

のいずれかが、WaitForSingleObject()の戻り値なんだが・・・
とりあえず、該当部分のコードを晒せ、晒したくなかったらコピペも満足にできない房は二度とくんな。

206 名前:>>46 mailto:sage [2006/01/21(土) 23:02:03 ]
>>199
> ソースを見る限りほかのスレッドが触ることはなさそ
> うなのですが確信持てないです。

はぁ? 悪いけど、変数がどっからアクセスされるか自信
が持てないなんて言う奴にはマルチスレッドプログラムは
無理だよ。あきらめたら?

>>203 で、デバッガとか言ってるが君がやることは、デ
バッガでプログラムを追っかけることではなく hEvent
で全ソースに対して findstr することだと思う。
(そこらじゅうで hEvent 使ってるなら、問題のところ
の変数名を変えるべき。)

>>201
うちでも、CreateEvent() 〜 SetEvent() 〜
WaitForSingleObject() 〜 CloseHandle() を
10,000,000 回実行したが、WAIT_OBJECT_0 しか
返らないよ。

>>202
その考え方はおかしいだろ。
>>196 みたいな動きをするイベントなんて使い物にな
らないと思う。

207 名前:デフォルトの名無しさん mailto:sage [2006/01/22(日) 08:57:50 ]
>>206
>>196 みたいな動きをするイベントなんて使い物にな
>らないと思う。
eventは許可するまで待たせておくことが目的の物だから、setは少しくらい遅れても良いと思う。
acquireI->releaseする同期モノのreleaseも同じ。

208 名前:>>46 mailto:sage [2006/01/22(日) 10:13:10 ]
>>207
少しってどれぐらい?
1秒なの? 1ms なの? 1μs なの?

他のスレッドに対して set の伝播が遅れるのは問題ない
けど、自スレッドに対して SetEvent() してからイベン
トがセットされるまでの間に「隙間」があるのは問題。

例えば、

SetEvent(hEvent); // hEvent は、ワーカースレッドか処理終了でセットする。
StartWorkerThread(); // 処理開始指示。
while(WaitForSingleObject(hEvent, 0) == WAIT_TIMEOUT){ // 終了したか?
 // 終了してないなら、他のことしてようっと。
}
(こんなプログラムは組むなと言う意見はまた別の機会に。)

と言うプログラムがうまく動かない。

動かないだけなら、まだしも下手するとうまく動いたり動
かなくなったりすると言う最悪パターンになる。

マルチスレッドプログラムやるなら「隙間」をもっと意識
できないとはまるよ。

209 名前:デフォルトの名無しさん mailto:sage [2006/01/22(日) 12:18:00 ]
>>208
「こんなプログラムは組むな」

210 名前:デフォルトの名無しさん mailto:sage [2006/01/22(日) 12:45:43 ]
>自スレッドに対して SetEvent() してからイベン
>トがセットされるまでの間に「隙間」があるのは問題。

いやだから、その隙間は無いんだって。
というか、先頭のSetEventはResetEventの間違いだよな、な。

211 名前:デフォルトの名無しさん mailto:sage [2006/01/22(日) 16:13:56 ]
スレ違いスマソ

下のスレでマルチコアについて侃侃諤諤の論争してるんですけど、
みなさんはこれからのマルチコア時代についてどう捉えていますか?

Intelの次世代CPUについて語ろう 21
pc7.2ch.net/test/read.cgi/jisaku/1136822334/

212 名前:デフォルトの名無しさん mailto:sage [2006/01/22(日) 17:12:45 ]
>>208
次にタスクスイッチが起こったときにsetしてくれればいい程度に思って使ってるね、私は。

>while(WaitForSingleObject(hEvent, 0) == WAIT_TIMEOUT){ // 終了したか?
普通スレッド終了の検知はスレッドのハンドルをWaitForSingleObjectの引数にする。
わざわざeventなんて作らない。
スレッドをプールするなんて言い訳は聞かない。

>>211
面倒なことはOSに任せて今まで通りにやる。

213 名前:>>46 mailto:sage [2006/01/22(日) 20:04:17 ]
>>210
すまん、勘違いだ。
セット側はさすがにちょっと考えにくいな。
(まあ、リセット側も無理矢理だが。)
ただ、セット側とリセット側で挙動が違うのはちょっと気
持ち悪い。

>>211
マルチコアって言ったって、マルチプロセサの一形態だろ。
別に何か変えないといけないのか?
専用のチューニングが必要になったらそのとき勉強するよ。

>>212
> 普通スレッド終了の検知はスレッドのハンドルを
> WaitForSingleObjectの引数にする。

スレッドの終了 ≠ 処理の終了

誰も、スレッドの終了の検知方法なんて聞いてないぞ。
最近知ったので、知ったかしたくなったのか?



214 名前:デフォルトの名無しさん mailto:sage [2006/01/22(日) 20:06:09 ]
さーしったかしったかたーこうりんだー
さーしったかしったかたーこうりんだー
みぎあしくんひだりあしくん

215 名前:デフォルトの名無しさん mailto:sage [2006/01/22(日) 20:17:49 ]
>>214
気が済んだか?
すっきりしたら、違うスレに行ってくれよな。

216 名前:デフォルトの名無しさん mailto:sage [2006/01/22(日) 20:27:26 ]
>>213
>スレッドの終了 ≠ 処理の終了
そういうことを言いたかったのか。

217 名前:デフォルトの名無しさん mailto:sage [2006/01/22(日) 21:08:07 ]
VC6.0でスレッドを生成するために、
_beginthreadexを使おうと思っていますが、
1プロセスあたりに生成できるスレッド数って
決まっているのでしょうか?
MSDNのCreateThreadのヘルプには、
2028との数字がありますが・・・

218 名前:デフォルトの名無しさん mailto:sage [2006/01/23(月) 00:53:27 ]
スタック用のメモリ領域が1MB確保されるんじゃなかったかな

219 名前:デフォルトの名無しさん mailto:sage [2006/01/23(月) 00:57:58 ]
そんなにスレッド作ってどうするの?

220 名前:デフォルトの名無しさん mailto:sage [2006/01/23(月) 22:02:30 ]
特殊用途か設計ミスか勘違い

221 名前:デフォルトの名無しさん mailto:sage [2006/01/23(月) 22:48:39 ]
>>217-220
まさに、その「設計ミス」(要は、バグ) で、
スレッド作りすぎてアプリケーションエラー
出しまくった俺が来ましたよ。

うちの環境だと、1600個位でおかしくなった。

ただスレッドを生成するのが、メーカー提供の
COM の中なので、生成する時にどんなエラー
が返ってきているかはよくわからん。

222 名前:デフォルトの名無しさん mailto:sage [2006/01/24(火) 14:21:13 ]
なんじゃそりゃ(´・ω・`)

223 名前:デフォルトの名無しさん mailto:sage [2006/01/24(火) 23:34:23 ]
>>196

例えば

1.CreateEvent の第2引数が FALSE(自動リセットオブジェクト)である
2.スレッドAが WaitForSingleObject(hEvent, INFINITE) している
3.スレッドBが SetEvent(hEvent) を呼び出す
4.スレッドAが待機状態から解放される
5.スレッドBが WaitForSingleObject(hEvent, 0) を呼び出す

こういう場合、他のスレッドが ResetEvent しなくても 5.は WAIT_TIMEOUT
を返すけど、CreateEvent の第2引数が TRUE なら WAIT_TIMEOUT を返すのは
おかしいね。



224 名前:デフォルトの名無しさん mailto:sage [2006/01/25(水) 20:29:21 ]
WAIT_OBJECT_TIMEOUT
って書いてたことがばれて逃げてったやつに追い討ちかけんなよ。

225 名前:デフォルトの名無しさん mailto:sage [2006/01/27(金) 17:33:55 ]
A.EXE と B.DLL があり、B.DLL が foo() という関数をエクスポートしており、
foo() は内部的に strtok 等の C ランタイム関数を呼ぶとする。

B.DLL 内部で _beginthread(ex) したスレッドの中で foo() を呼ぶのは当然問題
ないはずだけど、A.EXE が内部で CreateThread または _beginthread(ex) した
スレッドの中で B.DLL の foo() 関数を呼び出した場合、メモリリークするの?

B.DLL が DLL_THREAD_ATTACH/DETACH できちんとスレッドごとの初期化・後始末
をしていれば大丈夫そうな気がするんだけど、VC とか BC とかの C ランタイム
ライブラリはこの辺どうなってるんだろう。


226 名前:デフォルトの名無しさん mailto:sage [2006/01/27(金) 18:21:34 ]
CreateThreadで作ったスレッドはCランタイムライブラリを使ってはいけない。
スレッド内部でCランタイムライブラリを使いたい場合は、_beginthreadexを使おう。
_beginthreadはVBみたいなもんだと思おう。

詳しくはMSDNライブラリを参照のこと。

ttp://msdn.microsoft.com/library/ja/vclib/html/_crt__beginthread.2c_._beginthreadex.asp
ランタイム ライブラリ リファレンス
_beginthread、_beginthreadex

ttp://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/jpdllpro/html/_win32_createthread.asp
プラットフォーム SDK
CreateThread

ttp://support.microsoft.com/default.aspx?scid=kb;ja;104641
C ランタイム(CRT)関数と CreateThread ()を使用するの、説明

227 名前:デフォルトの名無しさん mailto:sage [2006/01/27(金) 20:30:26 ]
>>225
むしろ逆。
B.DLL内部で_beginthread(ex)したスレッドからA.EXE中の関数bar()を呼ぶとリークする。
ただしA.EXEがCRTとスタティックリンクしていて実行環境がWindows Server 2003より前の場合。
ttp://codezine.jp/a/article.aspx?aid=235&p=2#col4
CRTはソース公開されてるから気になるなら読むといいよ。
Express Editionだと付いてるか知らんけど。

228 名前:225 mailto:sage [2006/01/27(金) 23:32:29 ]
>>227
> B.DLL内部で_beginthread(ex)したスレッドからA.EXE中の関数bar()を呼ぶとリークする。

コールバック関数とかも、そのコールバック関数が自EXE で _beginthread(ex)
したスレッドから呼ばれないなら C ランタイムを使えないことになりますね。

>>227 の質問を繰り返すことになりますが、A.EXE 内部で _beginthread(ex) した
スレッドから B.DLL 中の関数 foo() を呼ぶのは大丈夫なんでしょうか。

DllMain の DLL_THREAD_ATTACH/DETACH はこのへんの問題を解決するための
機構だと思ってるので、きっと大丈夫なんだと自分に言い聞かせるようにし
てるんですが…。

229 名前:225 mailto:sage [2006/01/27(金) 23:34:18 ]
>>227
> CRTはソース公開されてるから気になるなら読むといいよ。

VC6 のソースを見る限りでは、DLL_THREAD_ATTACH/DETACH でスレッドごとの
初期化/後始末をしているようです。

CRT を使う DLL に関して、VC6 のソースを見た感じでは、その DLL が
C ランタイムをスタティックリンクしている場合は _DllMainCRTStartup 内で
DllMain を呼ぶ前に DisableThreadLibraryCalls を呼ばないようです。

MSVCRT.DLL を使用する場合は、ユーザー定義の DllMain がない場合のみ、
DisableThreadLibraryCalls を呼んでいるようです。DllMain があった場合、
DllMain 内部で DLL_THREAD_ATTACH/DETACH が必要になる可能性があるから
DisableThreadLibraryCalls を呼ばないようにしてるのでしょう。おそらく。

だから、EXE 側で作成したスレッド内で、DLL 側の C ランタイム関数を使う
関数を呼び出しても、DLL_THREAD_DETACH で後始末が行われるのでメモリリーク
は発生しないのではないかと思ってますが、それが明記されているドキュメント
が見当たらないので気になっています。

230 名前:225 mailto:sage [2006/01/27(金) 23:36:13 ]
EXE 側で作成したスレッド内で、DLL 側の関数(内部的に C ランタイム関数を
使うもの)を使えない(使うとメモリリークする)としたら、まともなマルチ
スレッドアプリケーションなんて開発出来ない気もします。

せめて malloc/free/new/delete くらいは問題なく使えるようでないと…。
でも、

support.microsoft.com/default.aspx?scid=kb;ja;104641

を見ると malloc も駄目みたいですよね…。実際のところどうなんでしょ。

231 名前:デフォルトの名無しさん mailto:sage [2006/01/28(土) 07:40:26 ]
実際のところってもなあ
hackして怪我するのってあほらしくないか

232 名前:デフォルトの名無しさん mailto:sage [2006/01/28(土) 10:30:25 ]
>>230
Cランタイム関数はスレッドなんてのが出来るまえのシロモノだからね。

漏れの知る限りでは、
リンクしてるCランタイムライブラリが同じでマルチスレッド対応なら、
EXEとDLLで相互に呼び合いとかしても別段問題ない。
なぜなら、Cランタイムが使う領域は_beginthread*()でスレッド生成時に
スレッドローカルに確保されて、そちらが使用されるから。
(→see AdvancedWindows)

ただし、_*thread*()はランタイムライブラリに含まれる関数だから、
異なるライブラリを混在すると問題になる場合がある。
MS libcmtとMSVCRTの混在も危険。
(→see MSDNの/MDあたりのオプションのヘルプ)

233 名前:デフォルトの名無しさん mailto:sage [2006/01/28(土) 10:43:44 ]
>>230
それ英語版の方読めよ。機械翻訳で日本語として成立してない。
support.microsoft.com/?scid=kb%3Ben-us%3B104641&x=11&y=5

> スレッド内部でCランタイムライブラリを使いたい場合は、_beginthreadexを使おう。

> calling malloc(), fopen(), _open(), strtok(), ctime(), or localtime()

も問題なし。_endthreadex() が、CRT per-thread data-block を後始末してくれるから。



234 名前:225 mailto:sage [2006/01/28(土) 14:56:16 ]
ちょっと試してみました。

B.DLL
void foo(void)
{
  char dummy[256];
  strtok(dummy, "");
}

A.EXE
DWORD WINAPI ThreadProc(void *pvParam)
{
  foo();//B.DLL 内の関数
  return 0;
}

void test(void)
{
  HANDLE hThread;
  DWORD dwThreadId;
  int i;
  for(i = 0; i < 10000; i++){
    hThread = (HANDLE)CreateThread(NULL,
                    0,
                    ThreadProc,
                    0,
                    0,
                    &dwThreadId);
    WaitForSingleObject(hThread, INFINITE);
    CloseHandle(hThread);
}
}

235 名前:225 mailto:sage [2006/01/28(土) 14:57:27 ]
>>234 の続き
1.A.EXE: BCB5 で作成、B.DLL: VC6 libcmt.lib で作成
2.A.EXE: BCB5 で作成、B.DLL: VC6 msvcrt.lib で作成
3.A.EXE: BCB5 で作成、B.DLL: BCB5 で作成

結果:
1:DllMain で DisableThreadLibraryCalls を呼ぶとメモリリークする
  (test を呼ぶ度にメモリ使用量が増える)
  DllMain で DisableThreadLibraryCalls を呼ばなければメモリリークしない
  (test を何回呼んでもメモリ使用量は変わらない)
2:DllMain で DisableThreadLibraryCalls を呼んでも呼ばなくてもメモリリークしない
3:DllMain で DisableThreadLibraryCalls を呼んでも呼ばなくてもメモリリークする

ちなみに

void foo(void)
{
  char* dummy = (char*)malloc(128);// char *dummy = new char[128];
  free(dummy);// delete[] dummy;
}

の場合、どの場合においてもメモリリークしない

236 名前:225 mailto:sage [2006/01/28(土) 14:59:56 ]
>>235 の続き
結論:
BCB5/VC6 で作成した B.DLL においては、C ランタイムルーチンのうち、少なくとも
malloc/free/new/delete しか使わない分には、A.EXE で作成したスレッド内で B.DLL
の関数を呼び出してもメモリリークしない。スレッドの作成に _beginthread(ex) を
使う必要もない。

VC6 で MSVCRT.DLL とリンクする B.DLL では、A.EXE で作成したスレッド内で B.DLL
の関数(内部で C ランタイム関数を呼ぶもの)を呼び出してもメモリリークしない。

VC6 で libcmt.lib とスタティックリンクする B.DLL では、DllMain で
DisableThreadLibraryCalls() を呼ばなければ、A.EXE で作成したスレッド内で
B.DLL の関数(内部で C ランタイム関数を呼ぶもの)を呼び出してもメモリリーク
しないが、DisableThreadLibraryCalls()を呼ぶと、B.DLL が内部で呼び出している
C ランタイムルーチンによってはメモリリークする可能性がある。

他にも色んな組み合わせが考えられますが、とりあえず自分が知りたかった
「A.EXE で作成したスレッド内で B.DLL 内の関数を呼び出してもメモリリーク
しないのか」は検証出来ました。この程度の実験で検証出来たと断言して良い
のかはわかりませんが。

BCB5 の C ランタイムルーチンは DLL_THREAD_ATTACH/DETACH をきちんと処理して
いないものと思われます。BCB5 で作った DLL はマルチスレッドアプリケーション
からは使いにくいですね。

VC7 以降とか GCC とかではどうなんでしょうね。

検証の仕方が間違ってたらご指摘下さい。

237 名前:デフォルトの名無しさん mailto:sage [2006/01/28(土) 15:25:22 ]
>>236
率直に言えば無意味な検証。
というのは、メモリリークだけが問題ではないから。

仮にメモリリークしていなかったとしても、
複数のスレッドで同時に1つのワークエリアを参照していれば、
各スレッドがお互いに1つのワークエリアをぶっ壊しあう。
喪前さんのやり方では、そのパターンが検出できない。

むしろ、メモリリークしている方が複数のスレッドで異なるワークエリアを作成している、
つまり不完全ながらもマルチスレッド対応しているという見方もできる。
(実際どうかは知らん。メモリだけ確保して1つのワークを壊しまくってる可能性もある)

つか、なんでCreateThread()で試してるんだ?
試すまでもなく駄目なの分かり切ってるだろ。
_beginthread*()ならまだわからんでもないが・・・。

238 名前:225 mailto:sage [2006/01/28(土) 18:02:37 ]
> 複数のスレッドで同時に1つのワークエリアを参照していれば、
> 各スレッドがお互いに1つのワークエリアをぶっ壊しあう。

マルチスレッド対応のランタイムでは、そのような問題は起こらないことが
保証されているものだと思ってました。
_beginthread(ex) の説明を読む限り、メモリリーク問題以外については
何も記述されていません。

> つか、なんでCreateThread()で試してるんだ?

確認したかったのは、「A.EXE で作成したスレッド内で B.DLL 内の関数を
呼ぶことが出来るかどうか」だからです。

A.EXE は BCB5 で作成していて、B.DLL は VC6 で作成しています。
B.DLL 内の C ランタイムルーチンを使うのに、A.EXE の _beginthread(ex)
を使っても無意味なのは初めからわかりきっています。

また、>>235 では書きませんでしたが、3.の場合、C ランタイムルーチン
はスタティックリンクされてるので、やはり A.EXE の _beginthread(ex)
と B.DLL の _beginthread(ex) は全く別物です。

> 試すまでもなく駄目なの分かり切ってるだろ。

メモリリークという点だけ見れば、駄目とは言い切れないという結果に
なったと思うのですが。元々 DLL_THREAD_ATTACH/DETACH で解決し得る
問題だと思ってるので、この結果がおかしいとは思えません。

239 名前:デフォルトの名無しさん mailto:sage [2006/01/28(土) 18:45:54 ]
>>238
> マルチスレッド対応のランタイムでは、そのような問題は起こらないことが
> 保証されているものだと思ってました。

思うのは勝手だけど、正しい使い方をしないと正しい挙動はしてくれないよ。
この場合、_beginthread*()を呼ばないと、「正しい挙動」はしてくれない。
なぜなら、Cランタイムをスレッドセーフにする肝心の処理を_beginthread*()がやるから。

ついでに言えば、問題はB.DLLだけの話ではなくて、A.EXEのランタイムに
何を使ってるか? というのも重要。にも関わらず、>>235でその点に
一切触れていない点からも、喪前さんの理解が足りないことが伺える。


240 名前:225 mailto:sage [2006/01/28(土) 20:18:06 ]
>>239
> なぜなら、Cランタイムをスレッドセーフにする肝心の処理を_beginthread*()がやるから。

_beginthread(ex) と _endthead がやるのは、スレッドごとに必要なメモリ
の割り当てと解放を行うことですよね?

_beginthread を使わなかったせいで、ランタイムルーチンを呼び出し時に
そのスレッドではまだメモリが割り当てられてなかったなら、その場で動的に
割り当てれば問題ないでしょう。実際、動的に割り当ててると思うんだけど。

問題なのは、スレッドの終了を知ることが出来なくなるせいで、割り当てた
メモリを解放する機会が得られなくなり、その結果としてメモリリークが発
生する、ということではないの?

_beginthread(ex) を使わないことによって、排他処理的な問題が起こるとは
どこにも書いてないですよね?起こらないとも書いてないけど。

排他処理的な問題が起こると明記されてるのは、シングルスレッド版の
ランタイムを使った場合の方だけです。
マルチスレッド版の方では、メモリリークのことしか書いてないと思う
んですけど。

> ついでに言えば、問題はB.DLLだけの話ではなくて、A.EXEのランタイムに
> 何を使ってるか? というのも重要。にも関わらず、>>235でその点に
> 一切触れていない点からも、喪前さんの理解が足りないことが伺える。

A.EXE は BCB5 で作成、B.DLL は VC6 で作成と書いてます。
理解が足りないのは認めますが。

長文ばかりで申し訳ない。

241 名前:デフォルトの名無しさん mailto:sage [2006/01/28(土) 20:54:27 ]
とりあえず消えろ

242 名前:225 mailto:sage [2006/01/28(土) 21:09:14 ]
>>241

真面目に質問してるつもりなんですが、そういうのが伝わらない
あたりが 2ch のイヤなところですね。

どこかにこの件に関してきちんと解説したウェブサイトなり書籍
があればご紹介頂きたかったですがね。

243 名前:デフォルトの名無しさん mailto:sage [2006/01/28(土) 21:19:39 ]
>>242
そういうのにいちいち気にしていたら駄目だよw

2chの使い方からまず学んだほうが有効に使えるかも。
当然俺のレスにもレスは要らないぞw(あってもいいけど



244 名前:225 mailto:sage [2006/01/28(土) 21:40:13 ]
>>243
やっぱりそうですか。(^^;

>>235 の結果から、(この検証が正しければ)メモリリークに関しては
処理系依存ということになったわけだし、ドキュメント化されてるわけ
でもないようだから、結局のところ結論なんて出ないんだろうな…。

「A.EXE で作成したスレッドから B.DLL の関数を呼び出すとメモリリークする」
のだとすると、Susie プラグインとか、自分ではメンテナンス出来ないプラグイン
方式の DLL を使うアプリをマルチスレッド化するのは非現実的ということになっ
てしまうのか…。ほとんどの DLL は C ランタイムを使用してるだろうから。

一度作成したスレッドはアプリが終了するまで使い回すようにするしかないの
だろうか…。なんか納得行かないな。

245 名前:デフォルトの名無しさん mailto:sage [2006/01/28(土) 22:06:40 ]
Susieプラグイン使う様なサイズのアプリなら、
スレッドプール使えば"about 70-80 bytes"のリークなんて気にする必要ないのでは?

>>242
MSDNだろ。


246 名前:241 mailto:sage [2006/01/28(土) 22:09:50 ]
マルチスレッドプログラミングをしたことのない房でも225のような真面目なやつを馬鹿にできるんだから
2chって憂さ晴らしに最適だよな。

247 名前:デフォルトの名無しさん mailto:sage [2006/01/28(土) 23:06:33 ]
>>231

248 名前:デフォルトの名無しさん mailto:sage [2006/01/29(日) 01:07:13 ]
>>244
真面目におかしなことばっかり言ってるから相手したくなくなるんだよ。
依存するのは処理系自体ではなくライブラリだし、
アンドキュメントな実装に依存したコードを書くのは無謀。

漏れが言えることは、
「EXE・DLLの両方で同じライブラリ使ってれば、相互に呼び合いしても問題ない」
「泥沼に足突っ込みたくなければ推奨されてるやり方を使え」
それだけ。普通にMSVCRT使えばいい。

それ以上のこと知りたいなら、AdvancedWindowsなりMSDNなりCRTのソースなり
自分で読んで勉強してくれ。スレでいちいち書けるほど単純な話でもない。

249 名前:225 mailto:sage [2006/01/29(日) 04:20:43 ]
>>248
> 「EXE・DLLの両方で同じライブラリ使ってれば、相互に呼び合いしても問題ない」

DLL は他人が作ってるので自分でいじれないし、EXE は GUI の
関係上 BCB しか使えないので。

> 「泥沼に足突っ込みたくなければ推奨されてるやり方を使え」

EXE で作成したスレッドから DLL の関数を呼ぶ場合の推奨されてる
やり方とは?EXE/DLL ともに MSVCRT を使うことですか?

> AdvancedWindowsなりMSDNなりCRTのソースなり自分で読んで勉強してくれ

MSDN と CRT のソースは自分なりに熟読してみたつもりです。
CRT のソースから、>>235 の結果は予想通りでした。
でも、3.の結果は予想通りだけど納得行かない。
BCB5 の C ランタイムライブラリのバグと言うべきなんじゃないだろうか。
仕様で片付けていい問題ではないような…。

AdvancedWindows を読んでもう少し勉強してみます。

250 名前:デフォルトの名無しさん mailto:sage [2006/01/29(日) 09:28:51 ]
最後のはBorlandのドキュメント読まないと仕方ないでしょ。
使ったことないから、どういう事になっているのか知らないし、
それで仕様通りの利用かどうかもわからない。

いずれにせよ、サードパーティのDLL内で、
CreateThread()を多発してない限り、別に大きな障壁になることじゃないよね。
スレッドを多発する場合、スレッドプール使うのは鉄則だから。

251 名前:デフォルトの名無しさん mailto:sage [2006/01/29(日) 18:37:53 ]
>>237>>239
やなやつだなあ。
まじめに答えてる振り装ってるが不快なことこの上ない。

252 名前:デフォルトの名無しさん mailto:sage [2006/01/29(日) 19:09:23 ]
まあスレッドプログラミングなんてやってる香具師はそんな香具師ばっかりだから

253 名前:デフォルトの名無しさん mailto:sage [2006/01/29(日) 19:30:17 ]
だから日本はだめなんだよな



254 名前:デフォルトの名無しさん mailto:sage [2006/01/29(日) 19:57:56 ]
>>252
いっしょにすな!

255 名前:デフォルトの名無しさん mailto:sage [2006/01/29(日) 21:20:17 ]
support.microsoft.com/?scid=kb%3Ben-us%3B104641&x=11&y=5
の"static"の使い方は違和感あるなあ。
"thread local"ってことだよな。実際は生存期間が"dynamic"だし。


256 名前:デフォルトの名無しさん [2006/01/30(月) 17:17:51 ]
マルチスレッドでプログラムを作っているのですが、VisualC++6.0(SP6)でデバッグすると
しばらくするとフリーズしてしまいます。
フリーズというのは、VC++と実行しているEXEがまったく応答しなくなり、
さらにOSの反応がほとんどなくなる感じです。
ほとんどというのは、Alt+Tabぐらいは効くのですが、タスクマネージャーも起動せず
他のアプリも、しばらく動くのですがじきに応答がなくなります。
デバッグではなく、ただEXEを実行した場合は普通です。
OSはWindowsXPHome SP2で、まあ標準的な環境だと思います。
1つ怪しいのといえば、NortonAntiVirusですが、これに関しては
ほぼインストールしたてのWin2000SP4のマシンでやっても同じような現象が
起こったので、他のアプリが邪魔している、というわけでもなさそうです。
それなりに長いソースなので、同様の問題が発生する簡単なソースをコピペします。


257 名前:256 [2006/01/30(月) 17:18:38 ]
#include <windows.h>
#include <stdio.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

char* szClassNme = "aaa";

DWORD WINAPI thread_proc(LPVOID param)
{
int i;

while(1)
{
i++;
Sleep(10);
}
}


258 名前:256 [2006/01/30(月) 17:19:29 ]
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInst,
LPSTR lpszCmdLine, int nCmdShow)
{
MSG msg;
WNDCLASS WClass;
HWND hWnd;
DWORD tid;

if (!hPreInst) {
WClass.style= CS_HREDRAW | CS_VREDRAW;
WClass.lpfnWndProc= WndProc;
WClass.cbClsExtra= 0;
WClass.cbWndExtra= 0;
WClass.hInstance= hInstance;
WClass.hIcon= NULL;
WClass.hCursor= LoadCursor(NULL, IDC_ARROW);
WClass.hbrBackground= (HBRUSH)GetStockObject(WHITE_BRUSH);
WClass.lpszMenuName= NULL;
WClass.lpszClassName= szClassNme;
if(!RegisterClass(&WClass))
return 0;
}

hWnd = CreateWindow(szClassNme, "aaa", WS_POPUP | WS_SYSMENU | WS_MINIMIZEBOX,
100, 100, 200, 200, NULL, NULL, hInstance, NULL);

ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);

CreateThread(NULL, 0, thread_proc, NULL, 0, &tid);


259 名前:256 [2006/01/30(月) 17:24:07 ]

while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return(DefWindowProc(hWnd, msg, wParam, lParam));
}
return 0;
}


260 名前:256 [2006/01/30(月) 17:30:36 ]
thread_procの、while(1)のところにブレークポイントを設定し
F5を連打し何回かループさせると、いずれ固まります。
ひょっとしてプログラムに何か原因があるのでしょうか?
デバッグがままならないとなると開発が非常に困難です。

261 名前:256 [2006/01/30(月) 20:19:40 ]
WinXPで、ウィンドウズキー+Lで、ユーザーを切り替ることはできたので
別のユーザーからMSDEV.exeを強制終了すると、一応復帰できることが分かりました。
しかし、依然として非常に困っています。
もし以前こんな現象に見舞われたけど、こうして直したよ、とか
ここをこうしたらいいんじゃないの?っていうのがありましたらぜひ教えていただきたいです。

262 名前:デフォルトの名無しさん mailto:sage [2006/01/30(月) 20:32:17 ]
osの再インストールしても直らなかったという、ほろ苦い思い出があるよ。

263 名前:256 mailto:sage [2006/01/30(月) 21:32:25 ]
>262
その後は結局どうなりました?
ひょっとしてマルチスレッドのデバッグは、VC++6.0でできないっていうのが
「仕様」なんでしょうか?



264 名前:デフォルトの名無しさん mailto:sage [2006/01/30(月) 21:52:07 ]
Windowsを2000にするか、VisualStudioをバージョンアップしませう

265 名前:256 mailto:sage [2006/01/30(月) 22:01:27 ]
>264
Windows2000でもなりました。
VisualStudioをバージョンアップですか.... 高かったんですよね。

266 名前:デフォルトの名無しさん mailto:sage [2006/01/30(月) 22:26:40 ]
>>256

私も Windows2000 から XP にアップグレードしてから似たような
現象が発生するようになりました。

VC++6.0 と BCB5 でそうなっていて、どちらもマルチスレッド
アプリケーションでなくても発生します。

なんか Window メッセージの送受信の応答がシステム全体でとてつもなく
遅くなる感じですね。バックグラウンドで音楽とか流していても、音楽は
普通に流れますが、ウィンドウの切り替えとかがものすごく遅くなります。
完全なフリーズじゃないだけに、諦めて電源を落とそうにも、落とすタイ
ミングに困ってしまうというか。

ttp://www.wg7.com/w2ktips/#CTFMON

これと似たような症状なんですが、私は試していません。言語バーが
使えなくなるのも困るので。

結構頻繁に起こるので辛いのですが、起こらないときは起こらないので、
そういうものだと思って諦めています。

267 名前:225 mailto:sage [2006/01/30(月) 22:43:46 ]
_beginthread(ex) の説明のところに、CreateThread だとメモリリークして
しまう C ランタイム関数の一覧でも書いてあれば良いんですけどね。

ttp://support.microsoft.com/?scid=kb%3Ben-us%3B104641&x=11&y=5

には malloc とか fopen でもメモリリークするようなことが書かれてるけど、
実際に試してみると、VC6/BCB5 どちらの場合もメモリリークしてるようには
思えないです。

ここに書かれてないものでは、rand() を使うとメモリリークしますね。
今回の呼び出しの結果が前回の呼び出しに依存するようなタイプの関数は
全滅なんでしょうね。

268 名前:256 [2006/01/30(月) 22:55:37 ]
>266
確かに今まで他のプログラムを組んでいるときにそういうことはありました。
しかし、今回はそれとはちょっと違うように思えるのです。
一度固まると、少なくとも20分ぐらいは待ってみたのですが復帰しませんでした。
しかも、ほぼ毎回起こります。

上のソースに何か問題点があるのでしょうか?
ウィンドウメッセージに応じて処理をするスレッド(最初に起動されたときのもの)
別に他の計算をするスレッドを別に作っています。
競合が起こっているのかと思い、上のような簡単な簡単なソースを書いてみたのですが
あれでも必ずといっていいほど起こります。
ちなみにWindowsMeでも起こりました。家のPC全滅です..

269 名前:266 mailto:sage [2006/01/31(火) 00:34:55 ]
最初は自分が書いたプログラムに原因があると思ってたのですが、
Web 上にある他人が書いたもののいくつかを自分の環境でコンパイル・実行
してもそうなるので、環境によるものだと思って諦めることにしました。

Windows2000 では問題なかったので、256 さんと私とでは状況が
少し異なりますね。マルチスレッドアプリケーションでなくても
発生しますし。お役に立てなくてすみません。

270 名前:デフォルトの名無しさん mailto:sage [2006/01/31(火) 01:33:38 ]
オレもよくなる。ステップ実行しているとなんでもないところで固まってCtrl+Alt+Delをやって再起動とかやるが
まったく動かず、次にAlt+Tabで悪あがき。選択した窓から順に固まる。
最後電源長押し、するとmsdev.exeを終了しています、かなんかがでて、msdev.exeが終了するとほかもサクサク終わる。
もちろんまったく終わらないでそのまま固まることもある。
DLLで提供される関数をステップオーバーしたときに出るとか、なんか最初はそんなことを思っていたけど
そうでもないらしい。


271 名前:デフォルトの名無しさん mailto:sage [2006/01/31(火) 09:31:42 ]
Windowsのスケジューラ糞馬鹿だから
タスクマネージャでMSDEV.EXEのプライオリティ上げろ。


272 名前:256 mailto:sage [2006/01/31(火) 21:11:22 ]
VisualStudio .NET 2003を入れてデバッグしてみたところ、簡単なものは
ほとんど固まらなくなりましたが(とはいえ、ごくたまに固まります)
開発しているプログラムは依然として固まるようです。
いまいちすっきりしないのですが、あまりこの問題にかまっている時間的
余裕も無いのでデバッグ時のみシングルスレッドで動くようにして
場当たり的な解決をすることにしました。
幸運にもあまり修正せずにすむに済みました。
依然として自分のプログラムに問題があるのかという不安はのこりますが...
266さんをはじめ、皆様、様々な情報提供ありがとうございます。
よくあることのようなので、少し安心しました。(していいのか!?)

273 名前:デフォルトの名無しさん mailto:sage [2006/01/31(火) 21:27:49 ]
>263
imeだか関係の問題だったはず。
ttp://ww1.enjoy.ne.jp/~turikiti/knowledge/program/oboegaki.htm
の、マルチスレッドの注意点の項を参考にしてみては?
私は効果なかったんですが・・・



274 名前:デフォルトの名無しさん mailto:sage [2006/02/01(水) 01:56:10 ]
257のコードで何にも問題は出なかったぞ。
F5押しっぱなしでも固まるどころか快調そのもの。
Dual Pentium III 1GHz, NT4.0 VC++ 6.0+Sp5


275 名前:デフォルトの名無しさん mailto:sage [2006/02/03(金) 16:12:33 ]
>>256
デバッグモードでなぜかおかしくなるというWin個体は確かにある。
どうしようもない。マシン変えろ






[ 続きを読む ] / [ 携帯版 ]

前100 次100 最新50 [ このスレをブックマーク! 携帯に送る ] 2chのread.cgiへ
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧]( ´∀`)<278KB

read.cgi ver5.27 [feat.BBS2 +1.6] / e.0.2 (02/09/03) / eucaly.net products.
担当:undef