【发布时间】:2016-11-17 12:43:28
【问题描述】:
我只是想确保我有正确的方法。
显然,在调试器下运行时,在无效句柄上调用CloseHandle() 将导致抛出异常。不确定这种行为记录在哪里,但 Google 上多次提到它。
嗯,我在调试时得到它,但是没有理由使句柄无效。
基本上线程是启动的,然后稍后检查是否挂起
auto waitResult = WaitForSingleObject( hThread, 100 );
if ( waitResult == WAIT_TIMEOUT )
{
// Handle hung thread stuff
// This branch is not executed and shown only for completeness
}
else
{
// Thread completed OK stuff
// Just saves some stuff produced by the thread.
}
// some stuff omitted
// just prior to procedure exit
if ( hThread != NULL )
{
CloseHandle( hThread );
// When running under a debugger, throws a 0xC0000008 here
// waitResult happens to be zero when this is happening
}
现在我不希望句柄无效,因为我刚刚成功完成了一个WaitForSingleObject() 。
那么当线程终止定义的行为时,线程上的句柄是否会变得无效? (如果再次使用句柄值,似乎会面临竞争条件的危险)?
当然我可以用try / catch 包裹CloseHandle()。但我想了解发生了什么。
我也不介意微软官方对 CloseHandle() 在调试时抛出 0xC0000008 的说法。
【问题讨论】:
-
你在“处理挂线的东西”中做什么?
-
Microsoft 非常关注允许句柄回收攻击的代码,这就是为什么当您连接了调试器时会得到诊断。请注意,您发布的代码非常错误。如果您对 hThread 有效,那么对其进行 NULL 测试完全没有意义。更糟糕的是, // Thread completed OK 具有高度误导性,因为您实际上并没有检查 WFSO 是否确实返回了 WAIT_OBJECT_0。因此,即使 在此代码运行之前,句柄也可能无效。
-
里面有一个
TerminateThread。 (我也讨厌)。但这应该对这个问题没有实际意义,因为在抛出异常时不会采用该分支。另一个分支,“Thread completed OK stuff”只是保存了一些结果。 -
@infixed
TerminateThread可以让你的整个程序处于未定义状态,因为线程持有的锁没有被释放。例如,如果在线程分配新堆块时调用TerminateThread,则不会释放堆序列化锁。 -
@HansPassant 遵循 SE 指南,我试图将注意力集中在问题上,省略不相关的内容。未显示线程句柄的创建。提到了
WaitForSingleObject没有问题的事实。并且应该确定它在那个时候是有效的。 null 检查在程序结束时进行清理,并且可以通过goto(遗留代码,不是我的想法)在线程句柄被获取之前。
标签: c++ windows debugging exception