C Winsock接受内存泄漏/资源泄漏



我写了一个小的测试TCP侦听器。侦听器说,在端口28328上听着,效果很棒,期望每次客户连接到它时都会发生巨大的资源/内存泄漏。

#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
SOCKET Socket = INVALID_SOCKET;
bool TestServer()
{
    WSADATA wsaData = { 0 };
    if (WSAStartup(MAKEWORD(2, 2), &wsaData))
        return false;
    sockaddr_in addr = { 0 };
    Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    int Enable = 1;
    setsockopt(Socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&Enable, sizeof(int));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(28328);
    addr.sin_addr.s_addr = INADDR_ANY;
    if (bind(Socket, (sockaddr*)&addr, sizeof(sockaddr)))
        return false;
    if (listen(Socket, 50))
        return false;
    return true;
}

void Dolisten()
{
    if (TestServer())
    {
        sockaddr_in addr = { 0 };
        SOCKET Client_Socket = 0;
        int Lenght = sizeof(addr);
        for (;;)
        {
            Client_Socket = INVALID_SOCKET;
            Client_Socket = accept(Socket, (struct sockaddr *)&addr, &Lenght);
            if (Client_Socket == INVALID_SOCKET)
                continue;
            printf("Client Connected %Xn", Client_Socket);
            shutdown(Client_Socket, 2);
            closesocket(Client_Socket);
        }
    }
}

int main(int argc, char* argv[])
{
    Dolisten();
    WSACleanup();
    return 0;
}

虽然原始听众比这大得多,并且可能还有更多我尚未遇到的问题,但现在这是我最大的问题。

我假设问题是由于接受插座而发生的,并且无法正确关闭,然后泄漏到手柄泄漏。我基于以下事实:当我查看任务管理器和其他监视过程的工具时,我可以看到手柄计数以与我的连接相同的速度增加。

注意:

1)从外观上看,泄漏发生在非页码内存上。

2)如果在Linux环境中进行了编译和使用,则相同的代码片段不会产生相同的内存/资源泄漏。

3)我已经在多个Windows机器上编译并测试了此代码,并且发生了同样的问题。

4)(编辑)我确实看到了几个在某些MSDN论坛和VS论坛上发布此确切问题的人,但他们被告知要做的只是提交票。

您显示的应用程序中没有内存泄漏。

由于TCP/IP的工作方式,与封闭连接相关的资源无法立即释放。连接关闭后,数据包可能会停止或重新进行。因此,即使打电话给closesocket,实际的OS插座仍保持预定量的时间(通常为2-3分钟,可以使用TCPTIMEDWAITDELAY调整)。

如果运行netstat -an,您会在CLOSS_WAIT或TIME_WAIT状态下看到一堆连接:

  TCP    127.0.0.1:28328        127.0.0.1:56508        TIME_WAIT
  TCP    127.0.0.1:28328        127.0.0.1:56510        TIME_WAIT
  TCP    127.0.0.1:28328        127.0.0.1:56512        TIME_WAIT
  TCP    127.0.0.1:28328        127.0.0.1:56514        TIME_WAIT
  TCP    127.0.0.1:28328        127.0.0.1:56516        TIME_WAIT
  . . .

当然需要(内核)存储器来存储这些临时状态。

此外,无法立即重复使用来自临时范围的TCP端口号,这意味着您可以打开/关闭连接的 rate

非每页池是一个内核资源,与操作系统无法分配的内存有关,并且是稀缺的资源。因此,请密切关注它是一件好事。

它在内核中的事实意味着内存不直接在您的控件中。内存可能与未列,未加工的数据包有关,在这种情况下,资源是您间接负责您程序的责任。

检查手柄泄漏 - 来自哪里。应用程序验证者Microsoft:应用程序验证程序下载可以帮助识别泄漏内存和手柄的呼叫堆栈。

最新更新