【问题标题】:Thread handle validity after thread completion affecting debugging?线程完成后线程句柄有效性影响调试?
【发布时间】: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


【解决方案1】:

根据Raymond Chen的cmets,我调查了我正在使用的句柄是否可能无效,并且惊讶地发现微软居然说线程创建API_beginthread()实际上可以返回一个无效的句柄或另一个线程的句柄.

WaitOnSingleObject() 好像觉得句柄没问题。但如果线程句柄在等待期间关闭,Microsoft 会警告未定义的行为。因此,让我们留下未定义行为的可能性。

如果句柄的有效性很重要,Microsoft 的线程文档建议使用 _beginthreadex() 而不是 _beginthread()

Raymond 对此进行了补充,他指出另一部分说 “_endthread 会自动关闭线程句柄,而 _endthreadex 不会。因此,当您使用 _beginthread 和 _endthread 时,请不要通过调用 Win32 CloseHandle API 显式关闭线程句柄。此行为与 Win32 ExitThread API 不同。”

【讨论】:

  • 哦,你使用的是_beginthread。该函数为explicitly documented as“当你使用_beginthread和_endthread时,不要通过调用Win32 CloseHandle API显式关闭线程句柄。”
猜你喜欢
  • 2011-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多