C++ 线程完成后线程句柄的有效性是否影响调试?

C++ 线程完成后线程句柄的有效性是否影响调试?,c++,windows,debugging,exception,C++,Windows,Debugging,Exception,我只是想确定我有正确的想法 显然,在调试器下运行时,对无效句柄调用CloseHandle()将导致引发异常。不确定这种行为是在哪里记录的,但在谷歌上有多次提及 嗯,我是在调试时得到它的,但是没有理由使句柄无效 基本上线程是启动的,然后检查线程是否挂起 auto waitResult = WaitForSingleObject( hThread, 100 ); if ( waitResult == WAIT_TIMEOUT ) { // Handle hung thread stuff

我只是想确定我有正确的想法

显然,在调试器下运行时,对无效句柄调用
CloseHandle()
将导致引发异常。不确定这种行为是在哪里记录的,但在谷歌上有多次提及

嗯,我是在调试时得到它的,但是没有理由使句柄无效

基本上线程是启动的,然后检查线程是否挂起

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。

根据Raymond Chen的评论,我调查了我使用的句柄是否无效,并惊讶地发现微软居然说线程创建API
\u beginthread()
实际上可能返回无效句柄或另一个线程的句柄

WaitOnSingleObject()
似乎认为句柄没有问题。但是,如果线程句柄在等待期间关闭,Microsoft会对未定义的行为发出警告。因此,让我们来讨论一下,在这里存在未定义行为的可能性

如果句柄的有效性很重要,Microsoft关于线程的文档建议使用
\u beginthreadex()
而不是
\u beginthread()

雷蒙德补充说,另一节说
“\u endthread会自动关闭线程句柄,而\u endthreadex不会。因此,当您使用\u beginthread和\u endthread时,不要通过调用Win32 CloseHandle API来显式关闭线程句柄。此行为不同于Win32 ExitThread API。”

在“句柄挂起的线程”中做什么?”?Microsoft非常关注允许处理回收攻击的代码,这就是为什么在附加了调试器时会得到诊断。请注意,您发布的代码有很多错误。如果您确信hThread是有效的,那么测试它是否为NULL就毫无意义。更糟糕的是,//Thread completed OK具有很强的误导性,因为您实际上没有检查WFSO是否实际返回了WAIT\u OBJECT\u 0。因此,即使在此代码运行之前,句柄也可能无效。其中有一个
TerminateThread
。(我也讨厌它)。但是这个问题应该是没有意义的,因为当抛出异常时,不会执行该分支。另一个分支“Thread completed OK stuff”只保存了一些结果。@infixed
TerminateThread
会使整个程序处于未定义状态,因为线程持有的锁不会被释放。例如,如果在线程分配新的堆块时调用了
TerminateThread
,那么堆序列化锁将不会被释放。@HansPassant根据SE准则,我试图将重点放在问题上,忽略了不相关的内容。未显示线程句柄的创建。有人提到,
WaitForSingleObject
对它没有问题,并且应该确定它在这一点上是有效的。在过程结束时,null检查正在清理中,可以在获取线程句柄之前通过
goto
(遗留代码,不是我的主意)到达。哦,您使用的是
\u beginthread
。该函数是“当您使用_beginthread和_endthread时,不要通过调用Win32 CloseHandle API显式关闭线程句柄。”