我在旧的c ++应用程序中寻找一些随机崩溃。使用sysinternals进程资源管理器,我注意到应用程序丢失了句柄,并提取了确切的情况,程序正在丢失处理一小段代码。
DWORD WINAPI MyTestThread( void* PThread)
{
_endthreadex(0);
return 0;
}
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR PParameter, int)
{
for (int i=0;i<10000;i++)
{
unsigned int threadID;
HANDLE hThread= (HANDLE)_beginthreadex( (void*)NULL, (unsigned int)32768, (unsigned int (__stdcall *)(void *))MyTestThread, (void*)NULL, (unsigned int)0, &threadID);
WaitForSingleObject((HANDLE)hThread, 1000);
CloseHandle((HANDLE)hThread);
}
return 0;
}
我的问题:我无法弄清楚这段代码有什么问题。它在每次迭代时都会丢失5个句柄,但对我来说它看起来还不错 有趣的是:它似乎没有丢失Windows Vista上的句柄,但如果这应该是Windows 7中的错误,我会感到非常惊讶。
[更新]我尝试使用_beginthread / _endthread和CreateThread / ExitThread,这两个也失去了5个句柄,就像_beginthreadex一样。
[2nd Update]代码确实按预期运行。所有返回值都很好。这只是“只是”丢失手柄,就像没有明天一样。
[3rd Update] Big new Info 如果用/ clr编译,代码只会丢失句柄!而且,如果我在每次迭代时调用GC :: Collect(),则会回收句柄! 那么,我如何找到那里收集的clr-objects?
答案 0 :(得分:2)
检查链接到你的exe的某些DLL是否在其DLLMain中做了一些奇怪的事情以响应DLL_THREAD_ATTACH通知。
答案 1 :(得分:1)
您是否检查过这些功能是否成功?返回值和GetLastError()
可以提供一些错误。
答案 2 :(得分:1)
来自http://msdn.microsoft.com/en-us/library/kdzttdcb.aspx
“如果成功,这些函数中的每一个都会返回新创建的线程的句柄;但是,如果新创建的线程退出太快,_beginthread可能不会返回有效句柄(请参阅”备注“部分中的讨论)._ beginthread返回-1L出现错误,在这种情况下,如果线程太多,则errno设置为EAGAIN;如果参数无效或堆栈大小不正确,则设置为EINVAL;如果资源不足(例如内存),则设置为EACCES。 _beginthreadex在出错时返回0,在这种情况下设置了errno和_doserrno。“
你的线程确实很快就会退出。
答案 3 :(得分:0)
您是否尝试使用Win32的CreateThread进行测试?这可能会将问题缩小到CRT。