我有一个非常奇怪的问题。在网上寻找原因并尝试一切。什么都没有帮助。
第一种情况:
(这与预期完全一样.Windows任务管理器显示常量内存大小,但不会增加。)
unsigned long WINAPI thfun(void * arg)
{
::Sleep(50);
::ExitThread(0);
return 0;
}
int main(int argc, const wchar_t ** argv)
{
HANDLE th = 0;
DWORD thid, err;
while (true)
{
th = ::CreateThread(0, 0, thfun, 0, 0, &thid);
if (!th)
{
err = ::GetLastError();
}
::WaitForSingleObject(th, INFINITE);
}
return 0;
}
第二种情况:
unsigned long WINAPI thfun(void * arg)
{
::Sleep(50);
::ExitThread(0);
return 0;
}
int main(int argc, const wchar_t ** argv)
{
WORD ver;
WSADATA wsadata;
ver = MAKEWORD(2, 2);
if (WSAStartup(ver, &wsadata)) return 1;
::Sleep(50);
HANDLE th = 0;
DWORD thid, err;
while (true)
{
th = ::CreateThread(0, 0, thfun, 0, 0, &thid);
if (!th)
{
err = ::GetLastError();
}
::WaitForSingleObject(th, INFINITE);
}
return 0;
}
如果我从winsock调用任何函数,则一旦创建的线程不释放内存。 Windows任务管理器显示了我的应用程序不断增长的内存。
当我使用winsock时,我应该怎样做才能达到与第一种情况相同的行为?
我使用visual studio 2013
非常感谢您的帮助
答案 0 :(得分:1)
您不要关闭线程句柄。一个常见的错误。
你的核心循环应该是这样的:
while (true)
{
th = ::CreateThread(0, 0, thfun, 0, 0, &thid);
if (!th)
{
err = ::GetLastError();
}
::WaitForSingleObject(th, INFINITE);
CloseHandle(th);
}
这两个例子都存在这个问题。第二个样本的记忆增长可能是副作用。
ExitThread(0)
从来都不是一个好主意,我不明白为什么微软推荐它为C.因为Winsock API不应该有任何析构函数,它应该不是问题。不过,不要使用它。
<强>更新强>
我在安装了Antivira个人计算机(我的游戏机)的Windows 7 64位SP1系统上测试了您的代码。也在我的Windows 8 VM(并行)上。两个系统都没有显示您描述的问题并在您的视频中显示。这是恕我直言的好消息,因为它似乎是你的安装问题而不是一般问题。 视频显示每个结束线程只有几个字节的泄漏,每个线程严格线性增长。这就像线程相关信息一样,通常存储在TLS中( T hread L ocal S torage)。此外,它仅在您初始化WSASocket系统时出现。如果WSASocket系统本身就是问题,我们肯定会找到它的报告(但我没有)。我相信一个钩子DLL导致了这个问题,一个DLL通过DllMain通知该进程的任何已启动或结束的线程。任何病毒扫描程序或键盘插件(!)都可能导致这样的问题,因为它们通常使用钩子DLL并操纵管道和套接字等IO。
不幸的是,我只知道一种方法:
停用或卸载挂钩可能会有所帮助,但不一定需要。不幸的是,在Windows系统上安装程序是最大的反转。
很抱歉没有轻易回答。