c++ - winsock和新线程不释放内存

标签 c++ multithreading winsock2

我有一个非常奇怪的问题。在网上寻找原因并尝试一切。没有任何帮助。

第一种情况:

(这完全符合预期。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。

不幸的是,我只知道一种查找方法:

  1. 对您的样本进行候选发布。确保问题存在。
  2. 全新安装 Windows 7
  3. 逐步安装您在生产系统上使用的环境。确保在每个步骤后重新启动计算机。
  4. 希望找到罪魁祸首。

停用或卸载 Hook 可能会有所帮助,但不是必需的。不幸的是,在 Windows 系统上安装程序是最大的逆向操作。

很抱歉没有给出简单的答案。

关于c++ - winsock和新线程不释放内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28528426/

相关文章:

c++ - 将顶点坐标转换为 "same"屏幕坐标

c++ - 我们是否可以保证任何原子写入都会立即将原子变量的新值存储在主内存中?

c++ - WinSock2 HTTP GET 用法

c++ - <functional>中有功能组合的东西吗?

c++ - 动态内存分配

python - 如何防止 FIFO 队列有条件挂起

java - 检查 java 线程是否已被 join()ed

objective-c - 如何结束使用 detachNewThreadSelector 创建的轮询线程?

c++ - 使用基于 IOCP 的客户端的每个 IO 数据

sockets - UDP套接字给出错误WSAETIMEDOUT