簡體   English   中英

C ++ Winsock接受內存泄漏/資源泄漏

[英]C++ Winsock Accept Memory leak/Resource Leak

我已經編寫了一個小型測試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 %X\n", 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論壇上看到幾個有這個確切問題的人,但是他們被告知要做的只是提交一張票。

非分頁池是內核資源,它與操作系統無法分頁的內存有關,是一種稀缺資源。 因此,關注它是一件好事。

它位於內核中,這意味着內存並不直接在您的控件中。 內存可能與未發送,未處理的數據包有關,在這種情況下,資源是程序的間接責任。

檢查手柄泄漏-泄漏來自何處。 應用程序驗證程序Microsoft:下載應用程序驗證程序可以幫助識別正在泄漏內存和句柄的調用堆棧。

您顯示的應用程序中沒有內存泄漏。

由於TCP / IP的工作方式,與封閉連接關聯的資源無法立即釋放。 連接關閉后,數據包可能會亂序到達或重新發送。 因此,即使在調用closesocket ,實際的OS套接字仍會在預定義的時間段內保持打開狀態(通常為2-3分鍾,可以使用TcpTimedWaitDelay進行調整)。

如果運行netstat -an ,則會看到一堆處於CLOSE_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端口號無法立即重用,這意味着打開/關閉連接的速率非常有限。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM