首页
社区
课程
招聘
[求助]关于WaitForSingleObject
发表于: 2009-10-17 18:17 5045

[求助]关于WaitForSingleObject

2009-10-17 18:17
5045
写了一个不规范的程序:
// threadSD0.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>

int a;
DWORD WINAPI incp(LPVOID lpParameter) {
	a++;
	ExitThread(0);
	return 0;
}
DWORD WINAPI decp(LPVOID lpParameter) {
	a--;
	ExitThread(0);
	return 0;
}
DWORD WINAPI prnp(LPVOID lpParameter) {
	printf("%2d",a);
	ExitThread(0);
	return 0;
}

int main(int argc, char* argv[])
{
	int delta=0;
	VOID* rr=NULL;
	UINT count=0;
	long t;
	long tmp;
	printf("input delta: ");
	scanf("%d",&delta);
	t=GetTickCount();
	tmp=GetTickCount();
	while(tmp-t<delta) {
		CreateThread(NULL,100,incp,NULL,0,0);
		CreateThread(NULL,100,decp,NULL,0,0);
		//rr=
			CreateThread(NULL,100,prnp,NULL,0,0);
		count++;
		tmp=GetTickCount();
	}
	WaitForSingleObject(rr,INFINITE);
	printf("\n-- Over Now...\n-- Times %u for Time %ld\n",count,tmp-t);
	return 0;
}

在“rr=”不被注释掉的情况下正常
在“rr=”被注释掉以后,即rr=NULL时,程序出现不可信状况……
描述:输入一个delta后,程序执行后有时会执行两次
printf("\n-- Over Now...\n-- Times %u for Time %ld\n",count,tmp-t);

但是不管哪一次,反汇编都是一样的:
24:
25:   int main(int argc, char* argv[])
26:   {
00401160 55                   push        ebp
00401161 8B EC                mov         ebp,esp
00401163 83 EC 54             sub         esp,54h
00401166 53                   push        ebx
00401167 56                   push        esi
00401168 57                   push        edi
00401169 8D 7D AC             lea         edi,[ebp-54h]
0040116C B9 15 00 00 00       mov         ecx,15h
00401171 B8 CC CC CC CC       mov         eax,0CCCCCCCCh
00401176 F3 AB                rep stos    dword ptr [edi]
27:       int delta=0;
00401178 C7 45 FC 00 00 00 00 mov         dword ptr [ebp-4],0
28:       VOID* rr=0;
0040117F C7 45 F8 00 00 00 00 mov         dword ptr [ebp-8],0
29:       UINT count=0;
00401186 C7 45 F4 00 00 00 00 mov         dword ptr [ebp-0Ch],0
30:       long t;
31:       long tmp;
32:       printf("input delta: ");
0040118D 68 3C 20 42 00       push        offset string "input delta: " (0042203c)
00401192 E8 89 01 00 00       call        printf (00401320)
00401197 83 C4 04             add         esp,4
33:       scanf("%d",&delta);
0040119A 8D 45 FC             lea         eax,[ebp-4]
0040119D 50                   push        eax
0040119E 68 38 20 42 00       push        offset string "%d" (00422038)
004011A3 E8 F8 01 00 00       call        scanf (004013a0)
004011A8 83 C4 08             add         esp,8
34:       t=GetTickCount();
004011AB 8B F4                mov         esi,esp
004011AD FF 15 5C 71 42 00    call        dword ptr [__imp__GetTickCount@0 (0042715c)]
004011B3 3B F4                cmp         esi,esp
004011B5 E8 26 01 00 00       call        __chkesp (004012e0)
004011BA 89 45 F0             mov         dword ptr [ebp-10h],eax
35:       tmp=GetTickCount();
004011BD 8B F4                mov         esi,esp
004011BF FF 15 5C 71 42 00    call        dword ptr [__imp__GetTickCount@0 (0042715c)]
004011C5 3B F4                cmp         esi,esp
004011C7 E8 14 01 00 00       call        __chkesp (004012e0)
004011CC 89 45 EC             mov         dword ptr [ebp-14h],eax
36:       while(tmp-t<delta) {
004011CF 8B 4D EC             mov         ecx,dword ptr [ebp-14h]
004011D2 2B 4D F0             sub         ecx,dword ptr [ebp-10h]
004011D5 3B 4D FC             cmp         ecx,dword ptr [ebp-4]
004011D8 7D 7A                jge         main+0F4h (00401254)
37:           CreateThread(NULL,100,incp,NULL,0,0);
004011DA 8B F4                mov         esi,esp
004011DC 6A 00                push        0
004011DE 6A 00                push        0
004011E0 6A 00                push        0
004011E2 68 14 10 40 00       push        offset @ILT+15(incp) (00401014)
004011E7 6A 64                push        64h
004011E9 6A 00                push        0
004011EB FF 15 58 71 42 00    call        dword ptr [__imp__CreateThread@24 (00427158)]
004011F1 3B F4                cmp         esi,esp
004011F3 E8 E8 00 00 00       call        __chkesp (004012e0)
38:           CreateThread(NULL,100,decp,NULL,0,0);
004011F8 8B F4                mov         esi,esp
004011FA 6A 00                push        0
004011FC 6A 00                push        0
004011FE 6A 00                push        0
00401200 68 05 10 40 00       push        offset @ILT+0(decp) (00401005)
00401205 6A 64                push        64h
00401207 6A 00                push        0
00401209 FF 15 58 71 42 00    call        dword ptr [__imp__CreateThread@24 (00427158)]
0040120F 3B F4                cmp         esi,esp
00401211 E8 CA 00 00 00       call        __chkesp (004012e0)
39:           CreateThread(NULL,100,prnp,NULL,0,0);
00401216 8B F4                mov         esi,esp
00401218 6A 00                push        0
0040121A 6A 00                push        0
0040121C 6A 00                push        0
0040121E 68 0A 10 40 00       push        offset @ILT+5(prnp) (0040100a)
00401223 6A 64                push        64h
00401225 6A 00                push        0
00401227 FF 15 58 71 42 00    call        dword ptr [__imp__CreateThread@24 (00427158)]
0040122D 3B F4                cmp         esi,esp
0040122F E8 AC 00 00 00       call        __chkesp (004012e0)
40:           count++;
00401234 8B 55 F4             mov         edx,dword ptr [ebp-0Ch]
00401237 83 C2 01             add         edx,1
0040123A 89 55 F4             mov         dword ptr [ebp-0Ch],edx
41:           tmp=GetTickCount();
0040123D 8B F4                mov         esi,esp
0040123F FF 15 5C 71 42 00    call        dword ptr [__imp__GetTickCount@0 (0042715c)]
00401245 3B F4                cmp         esi,esp
00401247 E8 94 00 00 00       call        __chkesp (004012e0)
0040124C 89 45 EC             mov         dword ptr [ebp-14h],eax
42:       }
0040124F E9 7B FF FF FF       jmp         main+6Fh (004011cf)
43:       WaitForSingleObject(rr,INFINITE);
00401254 8B F4                mov         esi,esp
00401256 6A FF                push        0FFh
00401258 8B 45 F8             mov         eax,dword ptr [ebp-8]
0040125B 50                   push        eax
0040125C FF 15 54 71 42 00    call        dword ptr [__imp__WaitForSingleObject@8 (00427154)]
00401262 3B F4                cmp         esi,esp
00401264 E8 77 00 00 00       call        __chkesp (004012e0)
44:       printf("\n-- Over Now...\n-- Times %u for Time %ld\n);",count,tmp-t);
00401269 8B 4D EC             mov         ecx,dword ptr [ebp-14h]
0040126C 2B 4D F0             sub         ecx,dword ptr [ebp-10h]
0040126F 51                   push        ecx
00401270 8B 55 F4             mov         edx,dword ptr [ebp-0Ch]
00401273 52                   push        edx
00401274 68 F8 2F 42 00       push        offset string "\n-- Over Now...\n-- Times %u for "... (00422ff8)
00401279 E8 A2 00 00 00       call        printf (00401320)
0040127E 83 C4 0C             add         esp,0Ch
45:       return 0;
00401281 33 C0                xor         eax,eax
46:   }
00401283 5F                   pop         edi
00401284 5E                   pop         esi
00401285 5B                   pop         ebx
00401286 83 C4 54             add         esp,54h
00401289 3B EC                cmp         ebp,esp
0040128B E8 50 00 00 00       call        __chkesp (004012e0)
00401290 8B E5                mov         esp,ebp
00401292 5D                   pop         ebp
00401293 C3                   ret

这是怎么回事呢?
WaitForSingleObject使用NULL后不是不等待了吗?
哪位大侠能帮忙分析下程序不可信的原因,谢谢!

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 428
活跃值: (293)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
关于WaitForSingleObject函数第二个参数用法,MSDN中解释得很清楚呀:

dwMilliseconds
[in] Time-out interval, in milliseconds. The function returns if the interval elapses, even if the object's state is nonsignaled. If dwMilliseconds is zero, the function tests the object's state and returns immediately. If dwMilliseconds is INFINITE, the function's time-out interval never elapses.

指定等待的时间间隔,以毫秒为单位。如果指定的时间间隔已过,即使所请求的对象仍处于无信号状态,WaiForSingleObject函数也会返回。如果将此参数设置为0(在afx.h中可以找到NULL是定义的宏,值为0),那么函数WaiForSingleObject函数将测试该对象的状态并立即返回;如果将此参数设置为INFINITE,则该函数会用袁的等待,直到等待的对象有信号状态才会返回。
2009-10-18 14:26
0
雪    币: 240
活跃值: (26)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
厄,我的问题是:
当WaiForSingleObject的是NULL(即WaiForSingleObject(NULL,INFINITE);),
printf("\n-- Over Now...\n-- Times %u for Time %ld\n",count,tmp-t);
有时会运行两次是什么原因.....

厄,不好意思,楼上摘的是MSDN.......貌似和问题有点差距...

附录:
当输入delta=2000时,

最后一个printf有时运行了两次,
不过实际滴答数差t-tmp不同,一个是2012,一个是2013

以上程序在:
VC6+Win2K下调试 和
VC6+WinVista下调试过
上传的附件:
2009-10-20 23:30
0
雪    币: 240
活跃值: (26)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
4
唉,没有人知道吗....
厄,还是继续研究ThreadPool吧.....
2009-10-21 22:24
0
雪    币: 222
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
您好!
     我试验了一下,即使WaitForSingleObject的第一个参数是0,也没有出现最后一个printf运行两次的情况。
另外,WaitForSingleObject的第一次参数值是句柄,这个句柄是调用进程的句柄表的索引值。所以WaitForSingleObject等待的是句柄表中索引值为0的那个对象,而这个对象是什么,我们不知道,在WaitForSingleObject函数调用之前,它是否已经被关闭(即CloseHandle(rr)),我们也不知道。如果在WaitForSingleObject函数调用之前,它已经被关闭(即CloseHandle(rr)),而且此时第二个参数是INFINITE的话,此函数的行为将不确定。(MSDN)。
2009-10-22 17:56
0
雪    币: 240
活跃值: (26)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
6
感谢wmhfzh的提示,
但0不是被定义成NULL了吗??
厄,还是不太懂……
而且还有一个信息是:
一般运行两次都是在程序刚编译并运行1-3次后产生,之后就很少产生,但有时也会两次……
2009-10-22 18:16
0
游客
登录 | 注册 方可回帖
返回
//