我有一个非常奇怪的问题。在网上寻找原因并尝试一切。没有任何帮助。
第一种情况:
(这完全符合预期。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
非常感谢您的帮助
最佳答案
您不会关闭您的线程句柄。常见错误。
你的核心循环应该是这样的:
while (true)
{
th = ::CreateThread(0, 0, thfun, 0, 0, &thid);
if (!th)
{
err = ::GetLastError();
}
::WaitForSingleObject(th, INFINITE);
CloseHandle(th);
}
你的两个例子都存在这个问题。第二个样本的内存增长可能是一个副作用。
ExitThread(0)
从来都不是一个好主意,我不明白为什么 Microsoft 为 C 推荐它。由于 Winsock API 不应该有任何析构函数,所以它应该不是问题。尽管如此,请不要使用它。
更新
我在安装了 Antivira 个人版(我的游戏机)的 Windows 7 64 位 SP1 系统上测试了您的代码作为发行版。同样在我的 Windows 8 VM(并行)上。两个系统都没有显示您描述和视频中显示的问题。恕我直言,这对您来说是个好消息,因为这似乎是您的安装问题,而不是一般问题。 该视频显示每个结束线程仅泄漏几个字节,并且每个线程严格线性增长。在我看来,这就像线程关联信息,如今通常存储在 TLS 中(Thread Llocal Storage)。它也只在你初始化 WSASocket 系统时出现。如果 WSASocket 系统本身就是问题所在,我们肯定会找到有关它的报告(但我没有)。我相信一个钩子(Hook) DLL 导致了这个问题,一个 DLL 通过 DllMain 被告知进程的任何开始或结束的线程。任何病毒扫描程序或键盘插件 (!) 都可能导致此类问题,因为它们通常使用 Hook DLL 并操纵管道和套接字等 IO。
不幸的是,我只知道一种查找方法:
- 对您的样本进行候选发布。确保问题存在。
- 全新安装 Windows 7
- 逐步安装您在生产系统上使用的环境。确保在每个步骤后重新启动计算机。
- 希望找到罪魁祸首。
停用或卸载 Hook 可能会有所帮助,但不是必需的。不幸的是,在 Windows 系统上安装程序是最大的逆向操作。
很抱歉没有给出简单的答案。
关于c++ - winsock和新线程不释放内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28528426/