マルチスレッドプログ ..
[2ch|▼Menu]
75:65
05/11/21 00:29:05
>>70 >>72
 Unixプログラミングすれから、誘導されたんですよ。
>>74
 実務レベルだと、
 親=オペレータが、起動スクリプト(セマフォ作成)をたたく。
    サーバー終了時に、終了スクリプトをたたく。

    オペレータ介さないと考えると、init.dに、SXXXXスクリプト)を作成し、
    runレベルに合わせて、起動、終了のシンボリックリンクをはる。
   
 なんて感じですかね。
            

76:デフォルトの名無しさん
05/11/21 02:49:56
>>75
そりゃ気の毒に、誘導が間違ってる。無責任にこの辺に誘導しとくよ。
「VIPPERでもわかるプログラミング」

77:デフォルトの名無しさん
05/11/21 12:01:13
>>73
過去の経験から言わせてもらうとライブラリ側で勝手にスレッドを起動するような
作りはあらゆる意味で良くない。
どうしても必要ならばまずそのスレッドで起こりえる可能性をすべて列挙してみる。
スレッドが起動するという事、その際例外が発生した場合どういう処置がなされるべきか、など。
判断がつかなければコールバック等でそのスレッドのトップレベルループや
ドメインに該当する処理に対してユーザーが干渉できるようにしたほうがいい。
↑domain
|user_thunk_procedure
|thread_callback
これらをドキュメント等も含めきちんと導出できないと第三者にはまず提供できない
代物になる。もしくは欠陥を持ったライブラリが完成する。


78:デフォルトの名無しさん
05/11/22 00:23:28
マルチスレッドの例外処理ってどうやってまつか、みなさん。


79:デフォルトの名無しさん
05/11/22 00:30:02
大域くくって落ちたらやりなおし、
ループでもなんでも、気をとりなおして次の処理。

80:73
05/11/22 01:45:30
>>77
ありがとうございますた、

厳しいみたいでつね、もっと勉強しまつ。


81:デフォルトの名無しさん
05/11/28 01:09:25
winapiスレと迷いましたが、_beginthreadex()に関して質問があります。

現在_beginthreadex(NULL, 0, .....);
としてメモリ割り当てを特に指定していません。

現在は実験のためにあるスレッドをいくつも作りたいのですが、
そうすると、エラーが起こりその原因の場所を調べると
#endif /* _WIN64 */
return HeapAlloc(_crtheap, 0, size);
という箇所でした。毎回ここでエラーが出ているようです。

この原因としてスタック領域のメモリ不足だと自分では思っているのですが、
実際のところはどうなのでしょうか?
また何かいい解決方法を教えていただけないでしょうか?
現在は数十スレですが、将来的には数百スレを扱いたいと考えています。

82:デフォルトの名無しさん
05/11/28 01:33:22
いいえ、その情報だけですとスタックではなくヒープの確保が失敗したと思われます。
マルチスレッド云々以前に初心者歓迎スレ辺りでソースを晒してみては如何でしょう。

83:デフォルトの名無しさん
05/11/28 01:40:39
スレッドが多すぎてヒープ(のアドレス空間)が足りなくなるという可能性も無くはないけど
数十スレッド程度でそんなことになる筈もなく
そもそもスタック領域がヒープを圧迫するかどうかという問題も

84:81
05/11/28 10:47:04
舌足らずですいません。
エラーが起こるのは_beginthreadex()内の処理のようです。
_beginthreadex()を呼び出して目的のスレッドを作成しようとすると
その過程の最中で81のようなエラーが出現してしまいます。

あと、
「メモリがreadになることはありませんでした。」
というメッセージボックスが表示されるのですが
何か関係あるのでしょうか?
スレッド数は32、64、96と増やしていきたいのですが
32の段階でのエラーです。

85:デフォルトの名無しさん
05/11/28 11:28:40
だから、マルチスレッド以前のレベルでバグってるんだろってば。
自分のソースも追えないような蛸なら初心者スレでソース晒せって。

86:デフォルトの名無しさん
05/11/28 13:27:17
> あと、
> 「メモリがreadになることはありませんでした。」
> というメッセージボックスが表示されるのですが

自分で確保したメモリ領域外のアドレスを読みに行ったときに出る.


87:デフォルトの名無しさん
05/11/28 16:58:56
エスパーの俺様が、スレ違いのバグを解決してやろう。

malloc系を呼び出したときにライブラリ内でエラーが起こるのは
ヒープの管理ブロックが壊れている時だ。

つまり、mallocした領域以外をfreeしたり、同じ領域を2度freeしたり
あるいは確保した領域をはみ出して書き込みをした場合に起こる。

88:81
05/11/28 22:43:36
すいませんでした
>87さんのレスを手がかりにmalloc(), free()を中心に調べていったところ
p = (int *)malloc(sizeof(short) * num);
という箇所がありました。
sizeof(int)に直したところ変なエラーはでなくなりました。
心配されていた方々申し訳ございませんでした。

89:デフォルトの名無しさん
05/11/29 00:00:44
だから>82や>85がマルチスレッド以前のバグだって指摘してたのに……

90:デフォルトの名無しさん
05/11/29 04:05:55
うるせえ黙れ

91:デフォルトの名無しさん
05/11/29 08:26:55
>>88
心配してねーよ。
こいつ馬鹿だなと思っていただけ。

92:デフォルトの名無しさん
05/11/29 09:50:47
>>88
誰も心配はしてないとおもいます。アドバイスしてただけ。
日常でもそのような勘違いをしているとなぜあの人は自分のことしか考えないのかと思われるので注意しましょう

93:愛也
05/11/29 15:57:01
質問なんですが・・・・どなたか教えていただけないでしょうか?

(1)
特定のデータを指定するにはアドレス信号を用いる。どれだけのアドレス信号が発行できるかはアドレスバスの本数による。
アドレスバスの本数が8本のときは(  1  )個、12本の時は(  2  )個のアドレスを発行する事ができる。

(2)
容量32KBのメモリがある、このメモリにバイト単位でアドレスをつけた場合(アドレス幅は8ビット)、全アドレスを指定するには、最低(  3  )本のアドレスバスが必要である。
同時に256MBの場合は(   4   )本必要である。

上の問題をどなたかお時間がある方がいらっしゃれば教えていただけないでしょうかぁ??

何卒よろしくお願い致します。

94:デフォルトの名無しさん
05/11/29 16:05:54
>>93
板違い

95:デフォルトの名無しさん
05/11/29 16:43:14
>>93
そのうえ問題自体に間違いがある(w
コピペミスかもしれんが(w


96:デフォルトの名無しさん
05/11/29 20:19:25
HTマシンでpause命令使って効果実感した人いる?


97:デフォルトの名無しさん
05/11/29 23:05:15
メール欄が空ですよ

98:デフォルトの名無しさん
05/12/06 03:43:50
93は、
スレ題名に「マルチスレッドプログラミング相談室」と書いてあるから、
「ここはマ板共用の相談スレに違いない!」と思ったんじゃないの?

99:デフォルトの名無しさん
05/12/06 12:03:49
マ板?

100:デフォルトの名無しさん
05/12/07 16:08:17
Windows でマルチスレッドを実現するには CreateThread API 以外に方法はありますでしょうか?

101:デフォルトの名無しさん
05/12/07 16:55:31
_beginthread

102:デフォルトの名無しさん
05/12/07 21:07:21
>>101
_beginthreadex使えよ。

103:デフォルトの名無しさん
05/12/09 18:32:43
つうか何がしたいんだ

104:デフォルトの名無しさん
05/12/09 18:52:57
いろんな恋がしたい

105:デフォルトの名無しさん
05/12/10 01:12:51
マルチフ恋奴

106:デフォルトの名無しさん
05/12/13 10:40:34
ほしょ

107:デフォルトの名無しさん
05/12/13 22:06:28
>>104
マルチスレッドな恋なんかしてると火吹くぞ

108:デフォルトの名無しさん
05/12/13 23:24:21
俺のセマフォは3カウントまで。

109:デフォルトの名無しさん
05/12/14 00:13:25
セマフォなんてニッチで泥臭いものは今日日使わないよ

110:デフォルトの名無しさん
05/12/14 00:29:54
オレのMutexは一度もLockされたことがない…orz

111:デフォルトの名無しさん
05/12/14 00:32:21
そこはまさにCriticalSectionなので、触れてはいけない。

112:デフォルトの名無しさん
05/12/14 00:33:55
一生一WorkerThread。

113:デフォルトの名無しさん
05/12/14 00:35:11
オレのFutureはいつまでたっても実体を返さない…orz

114:デフォルトの名無しさん
05/12/14 00:36:37
オレのQueueはいつも空っぽ…orz

115:デフォルトの名無しさん
05/12/14 00:44:57
Terminateされたい性分なんです、スレッド失格でしょうか?

116:デフォルトの名無しさん
05/12/14 00:50:19
だれかJoinしてクレー!

117:デフォルトの名無しさん
05/12/14 01:10:22
オレのQueue、気付いたときにはStackになってた

118:デフォルトの名無しさん
05/12/14 01:41:29
恋はいつも非同期(asyncronous)

119:デフォルトの名無しさん
05/12/14 02:02:00
クリスマスなのにDaemonです…orz

120:デフォルトの名無しさん
05/12/14 02:45:54
僕の人生Suspendしています。誰が解除してくれるんですか?

121:デフォルトの名無しさん
05/12/14 03:08:52
俺はreturnしちゃったよ

122:デフォルトの名無しさん
05/12/14 07:50:37
signal投げてくれる筈のプロセスがゾンビになっていた件について

123:デフォルトの名無しさん
05/12/14 07:55:39
それマルチスレッドじゃねーし

124:デフォルトの名無しさん
05/12/14 21:50:08
彼女といつも同期に失敗しまつ

125:デフォルトの名無しさん
05/12/14 21:52:06
俺はいつもシングルスレッド。

126:デフォルトの名無しさん
05/12/15 00:29:14
漏れのセフレはヂュアルコアだから2穴使って楽しめるよ。

127:デフォルトの名無しさん
05/12/17 01:08:57
おまいら、そろそろ戻ってこい

128:デフォルトの名無しさん
05/12/17 04:50:34
goto 107

129:デフォルトの名無しさん
05/12/17 08:34:28
mutex と spin lock の使い分けの基準て何?

130:デフォルトの名無しさん
05/12/17 10:49:07
使い分けってお前

131:デフォルトの名無しさん
05/12/17 15:45:08
mutex: 居間のテレビのチャンネル権取得に使う
spin lock: 朝、トイレの空きを待つ時に使う

132:デフォルトの名無しさん
05/12/17 15:57:25
後者、spin lockになるのはガマン出来ないときに限られると思われ

133:デフォルトの名無しさん
05/12/17 16:18:01
スピンロックって、カーネルモードへの移行よりも短い時間しかブロックされない処理、
例えば単純な変数の読み書きなんかに積極的に使いたくなるのだけれど

シングルプロセッサのシステムで、
ロックしているときにコンテキストスイッチが起きて
別スレッドがロック取得しようとすると
すげー時間が無駄になるんだよね。
それがちょっと嫌。

134:デフォルトの名無しさん
05/12/17 20:56:42
>>133
知ったかはよくないぞ。入社2年目のおぬし。天狗の鼻をへし折られろ。

135:デフォルトの名無しさん
05/12/17 21:16:38
我が社では、spin lock の事を
フレンドリーに「ぐるぐるくん」と呼んでいる。

136:デフォルトの名無しさん
05/12/17 21:35:35
我が社では回転元彌チョップと呼んでいる。

137:129
05/12/17 22:48:09
>>131
よくわからんです

>>133
その単純な変数の読み書き以外に、どうしても spin lock を使い
たいんじゃ! とか、spin lock じゃないとうまくいかないような、
典型的なケースってないすか?

138:デフォルトの名無しさん
05/12/18 00:05:24
>>134
じゃあ、どこがおかしいのか指摘しろよ。
業界最底辺を何年も続けてる事だけが自慢の
低脳プログラマさんよ。

マルチプロセッサでも、
ロックを取得している状態で実行権を奪われたら起こりうるのは確かだけどな。

139:デフォルトの名無しさん
05/12/18 00:40:53
>>138
だれか解読頼む。

140:デフォルトの名無しさん
05/12/18 01:43:49
>>138
お前の存在そのものがおかしいことを指摘してやらんでもない。

141:デフォルトの名無しさん
05/12/18 01:46:16
指摘してほしいのに しろよ はないだろ。
せめて、「わたくしは無知なので、できれば、ご指摘いただけないでしょうか?」だろ。
誠心誠意で言葉に気をつけろ。

142:デフォルトの名無しさん
05/12/18 01:51:21
ナニこいつ

143:デフォルトの名無しさん
05/12/18 01:59:03
具体的に指摘しないのは荒らしと同じだから放置汁

144:デフォルトの名無しさん
05/12/18 14:48:34
チョンはすぐにファビョるからやあねえ。

145:デフォルトの名無しさん
05/12/18 18:57:20
Win32(XP)で下のような排他制御を考えないプログラムを書いて
実際にハングするところを確かめたかったのですが、何度実行しても上手くハングしてくれません
たまたま運が良くてハングしなかっただけなのでしょうか?ご教示願います

#include <stdio.h>
#include <windows.h>
#include <process.h>
unsigned __stdcall mythread(LPVOID);
int main(){
unsigned int thID;
HANDLE hTh = (HANDLE)_beginthreadex(NULL, 0, mythread, NULL, 0, &thID);
for (int i = 1; i <= 100; i++) {
FILE *fp = fopen("test.txt", "a");
fprintf(fp, "Main---%d\n", i);
fclose(fp);
}
WaitForSingleObject(hTh, INFINITE);
CloseHandle(hTh);
return 0;
}
unsigned __stdcall mythread(LPVOID lpx)
{
for (int i = 1; i <= 100; i++) {
FILE *fp = fopen("test.txt", "a");
fprintf(fp, "Thread---%d\n", i);
fclose(fp);
}
return 0;
}


146:デフォルトの名無しさん
05/12/18 19:34:13
この程度でハングはしないと思うが、
同期とらない=ファイルの中身はグチャグチャになるの? 
って意味ならば出力されたファイルを読め。

147:デフォルトの名無しさん
05/12/18 19:38:13
>>146
ファイルもぐちゃぐちゃになりません。きちんと出力されます
また、一度に書き込む文字列のサイズを100KB程度と大きくしてもきちんとと出力されます
しかし、どちらかのスレッドにSleep(0)等を入れる程度でぐちゃぐちゃになります

境界はどこに有るのでしょうか?

148:デフォルトの名無しさん
05/12/18 21:36:48
ヒント:ストリーム系はバッファリングされるから混ざりにくい。

149:デフォルトの名無しさん
05/12/19 00:03:34
fprintf-fcloseの間にスレッドが切り替わらなければセーフ。
んで、100回くらいのループではWindowsのタイムスライスに
引っかからなかったりするのでは。
マルチプロセッサなら、カナリヒドい事になりそうな気がするのだけれど。

150:デフォルトの名無しさん
05/12/19 06:15:26
>>149
> fprintf-fcloseの間にスレッドが切り替わらなければセーフ。

そうとは限らない。


151:デフォルトの名無しさん
05/12/19 10:16:27
>>148
「一度に書き込む」っていってんだから、
バファリングの有無は関係ないような気がするんだけど。

152:デフォルトの名無しさん
05/12/19 21:48:15
そもそもハングするのか? ハングはしないだろ

153:145
05/12/20 01:28:57
いろいろ調べてましたが
IO絡みの関数は基本的にスレッドセーフに作られてるから
ってのが答えみたいです
お騒がせしました

>>149
それは違います。たとえfcloseをコメントアウトしてもハングしません

>>152
ハングはしないようですね
このページに「大抵ハングしてしまいます」と書かれていて気になったのです
URLリンク(www.kumei.ne.jp)
まあこのページに限らずネット上でマルチスレッドを初心者向けに教えているサイトでは
大抵同じような書かれ方がされてるので、
もしかすると私の検証が不十分なのかもしれませんが・・・



154:デフォルトの名無しさん
05/12/20 04:36:05
同時に書き込んで壊れなくても
後からの書き込みで前の書き込みは上書きされて消える訳だが

155:デフォルトの名無しさん
05/12/24 14:28:30
>>153
ランタイムライブラリがスレッドセーフで無い場合はハングするかもしれないけど、
VS2005からシングルスレッドのランタイムは無くなっているなあ。

156:デフォルトの名無しさん
05/12/24 14:44:54
「ハングする」なんて言い方は止めて、
「動作が未定義」くらいにしてくれないか。
本当にハングアップするかどうかを問題にしているんじゃないだろ?

157:デフォルトの名無しさん
05/12/25 13:24:46
>>156
このマニアめが。

158:デフォルトの名無しさん
05/12/25 13:38:00
/MT ってやってればたいがい大丈夫だろうけど、スレッドセーフでない関数で
gethostbynameとかが未定の動作されるとかなり困る、
無理矢理排他同期とって使ってるけどなんかかっこ悪い。


159:デフォルトの名無しさん
05/12/25 13:45:27
winsockのgethostbynameはスレッドセーフじゃなかったっけ?

160:デフォルトの名無しさん
05/12/25 13:49:25
/MTってことはWindows?
getaddrinfoはMT-Safeでしょ。

URLリンク(msdn.microsoft.com)
には明記してないけど、gai_strerrorは違うから〜って書いているくらいだから。

161:デフォルトの名無しさん
05/12/25 13:54:49
明記してあるな。

>Remarks
>The gethostbyname function returns a pointer to a hostent structure-a structure allocated by
>Windows Sockets. The hostent structure contains the results of a successful search for the
>host specified in the name parameter.
>The application must never attempt to modify this structure or to free any of its components.
>Furthermore, only one copy of this structure is allocated per thread, so the application should
                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> copy any information it needs before issuing any other Windows Sockets function calls.

162:デフォルトの名無しさん
05/12/25 13:57:38
struct hostent *host;
host = gethostbyname(argv[1]);

ってな形だし、どうみてもスレッドセーフでないと思ってた。
スレッド固有メモリなんてものでも使ってるのかな。

163:デフォルトの名無しさん
05/12/25 14:14:38
>>161
それだけでMT-Safeだとは限らない。

164:デフォルトの名無しさん
05/12/25 14:50:26
getaddrinfo ってのがあるんだ、
参考にしてた本が古っかったので知らなんだ。
該当箇所を書きかえねば orz

165:デフォルトの名無しさん
05/12/25 15:28:14
2ちゃんで書き込みするときの文字2048制限解除方法誰か教えてください。

166:デフォルトの名無しさん
05/12/25 15:29:18
制限解除して書き込んでる人が増えてるんですが

167:デフォルトの名無しさん
05/12/25 15:38:13
>>164
古いWindowsではありませんのでその辺は配慮を。

168:デフォルトの名無しさん
05/12/26 03:11:55
「スレッドできる」と「スレッドでファイル操作しても問題ない」は同義じゃないよなあ。
単一リソース操作は対策しないと普通は競合するよ。

169:デフォルトの名無しさん
05/12/26 19:09:27
マルチスレッドなサーバプログラムを作ってみようかと思ってます
クライアント数が少ない場合1クライアントに1スレッドを割り当てればいいかなと思いますが
クライアント数が多い場合はどういった方法が良いんでしょうか?
1スレッドあたりのクライアント数を決めてスレッドごとにselect()するとか
親スレッドでselect()して処理を別スレッドに任せるとか一応考えてはみていますが
どういった方法がスタンダードなんですかね?

170:デフォルトの名無しさん
05/12/26 20:42:42
ジョブキュー

171:デフォルトの名無しさん
05/12/26 22:37:27
+スレッドプール

172:デフォルトの名無しさん
05/12/26 23:38:08
裏技としてApache
勉強にはならんな・・・

173:デフォルトの名無しさん
05/12/27 13:56:11
apacheって何言ってんの?
ネットワークプログラミング相談室にも沸いたバカだろか。

174:デフォルトの名無しさん
05/12/28 15:39:12
なぜそこで、あと半歩踏み込んで「apache馬鹿よね〜」とか言えないよねぇ

175:デフォルトの名無しさん
05/12/28 16:51:48
おバカSunよね〜

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

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


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

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

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

180:デフォルトの名無しさん
06/01/03 04:40:29
>>179
前スレで延々やってたと思う

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

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

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

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

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

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

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

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

185:デフォルトの名無しさん
06/01/13 02:19:22
ひとつ!急いで口で吸え!

186:デフォルトの名無しさん
06/01/18 14:53:41
ふたつ! 不埓な悪行三昧!


187:デフォルトの名無しさん
06/01/18 16:18:23
みっつ! 想定の範囲内です。

188:デフォルトの名無しさん
06/01/18 16:55:53
よっつ、読んでも書いちゃダメ


189:デフォルトの名無しさん
06/01/18 16:56:28
いつつ、いつも心に排他処理


190:デフォルトの名無しさん
06/01/18 16:59:48
むっつ、無理せずmutex


191:デフォルトの名無しさん
06/01/18 17:21:48
ななつ、仲良くSemaphoeで共有

192:>>46
06/01/18 23:32:09
やっつ、やっぱりここでも排他処理

193:デフォルトの名無しさん
06/01/19 00:43:25
ここのつ!心を鬼にして排他処理

194:デフォルトの名無しさん
06/01/19 01:03:03
糞スレ立てんな

195:デフォルトの名無しさん
06/01/19 01:39:58
とう、でとうとう割り込まれた。

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

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




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

198:>>46
06/01/21 09:16:54
>>196
他のスレッドが一生懸命 ResetEvent(hEvent) を
やってる。

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

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


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

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

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

203:196
06/01/21 15:47:24
>>200
SetEventしてそれが本当にシグナルになったかを見るためにWaifFor・・したのですが、
それがなぜかシグナルになっていないのです。

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


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

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


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

205:デフォルトの名無しさん
06/01/21 21:15:12
そもそも、WAIT_OBJECT_TIMEOUTってなんだ?

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

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

206:>>46
06/01/21 23:02:03
>>199
> ソースを見る限りほかのスレッドが触ることはなさそ
> うなのですが確信持てないです。

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

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

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

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

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

208:>>46
06/01/22 10:13:10
>>207
少しってどれぐらい?
1秒なの? 1ms なの? 1μs なの?

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

例えば、

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

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

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

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

209:デフォルトの名無しさん
06/01/22 12:18:00
>>208
「こんなプログラムは組むな」

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

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

211:デフォルトの名無しさん
06/01/22 16:13:56
スレ違いスマソ

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

Intelの次世代CPUについて語ろう 21
スレリンク(jisaku板)

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

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

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

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

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

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

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

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

214:デフォルトの名無しさん
06/01/22 20:06:09
さーしったかしったかたーこうりんだー
さーしったかしったかたーこうりんだー
みぎあしくんひだりあしくん

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

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

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

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

219:デフォルトの名無しさん
06/01/23 00:57:58
そんなにスレッド作ってどうするの?

220:デフォルトの名無しさん
06/01/23 22:02:30
特殊用途か設計ミスか勘違い

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

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

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

222:デフォルトの名無しさん
06/01/24 14:21:13
なんじゃそりゃ(´・ω・`)

223:デフォルトの名無しさん
06/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:デフォルトの名無しさん
06/01/25 20:29:21
WAIT_OBJECT_TIMEOUT
って書いてたことがばれて逃げてったやつに追い討ちかけんなよ。

225:デフォルトの名無しさん
06/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:デフォルトの名無しさん
06/01/27 18:21:34
CreateThreadで作ったスレッドはCランタイムライブラリを使ってはいけない。
スレッド内部でCランタイムライブラリを使いたい場合は、_beginthreadexを使おう。
_beginthreadはVBみたいなもんだと思おう。

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

URLリンク(msdn.microsoft.com)
ランタイム ライブラリ リファレンス
_beginthread、_beginthreadex

URLリンク(www.microsoft.com)
プラットフォーム SDK
CreateThread

URLリンク(support.microsoft.com)
C ランタイム(CRT)関数と CreateThread ()を使用するの、説明

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

228:225
06/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
06/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
06/01/27 23:36:13
EXE 側で作成したスレッド内で、DLL 側の関数(内部的に C ランタイム関数を
使うもの)を使えない(使うとメモリリークする)としたら、まともなマルチ
スレッドアプリケーションなんて開発出来ない気もします。

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

URLリンク(support.microsoft.com)

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

231:デフォルトの名無しさん
06/01/28 07:40:26
実際のところってもなあ
hackして怪我するのってあほらしくないか

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

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

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

233:デフォルトの名無しさん
06/01/28 10:43:44
>>230
それ英語版の方読めよ。機械翻訳で日本語として成立してない。
URLリンク(support.microsoft.com)

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

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

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

234:225
06/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
06/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
06/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:デフォルトの名無しさん
06/01/28 15:25:22
>>236
率直に言えば無意味な検証。
というのは、メモリリークだけが問題ではないから。

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

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

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

238:225
06/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:デフォルトの名無しさん
06/01/28 18:45:54
>>238
> マルチスレッド対応のランタイムでは、そのような問題は起こらないことが
> 保証されているものだと思ってました。

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

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


240:225
06/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:デフォルトの名無しさん
06/01/28 20:54:27
とりあえず消えろ

242:225
06/01/28 21:09:14
>>241

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

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

243:デフォルトの名無しさん
06/01/28 21:19:39
>>242
そういうのにいちいち気にしていたら駄目だよw

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

244:225
06/01/28 21:40:13
>>243
やっぱりそうですか。(^^;

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

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

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

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

>>242
MSDNだろ。


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

247:デフォルトの名無しさん
06/01/28 23:06:33
>>231

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

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

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


次ページ
最新レス表示
スレッドの検索
類似スレ一覧
話題のニュース
おまかせリスト
▼オプションを表示
暇つぶし2ch

5353日前に更新/278 KB
担当:undef