簡體   English   中英

內存泄漏-與套接字或字符串相關?

[英]Memory Leak - Socket or String related?

我有一個簡單的功能,可以讓我獲取服務器上文件的內容。 它按照我想要的方式工作, 但是 “ Visual Leak Detector”指出在closeSocket(...)行上存在內存泄漏。

代碼如下:

string executeUrl(const char *url)
{
    SOCKET sConnection;
    char szHeader[500];

    sprintf(szHeader, "GET %s HTTP/1.0\r\n"
    "Host: %s\r\n"
    "User-Agent: Agent\r\n"
    "\r\n", url, HTTPSERVER);

    sConnection = HTTPConnectToServer(HTTPSERVER);
    if (sConnection == 0)
    {
        return "";
    }
    send(sConnection, szHeader, strlen(szHeader), 0);
    char reply[1024];
    ZeroMemory(reply, 1024);
    if (recv(sConnection, reply, 1024, 0) == SOCKET_ERROR)
    {
        return "";
    }
    string returnString(reply);
    closesocket(sConnection);
    WSACleanup();
    return returnString;
}

泄漏的數據字符串returnString 因此,它要么與字符串相關,要么與closesocket()

我讀了一些書,但無法弄清楚。 顯然,字符串應該照顧好自己並且不會引起內存泄漏,應該嗎?


編輯:

我嘗試了以下代碼: http : //www.zedwood.com/article/cpp-winsock-basic-http-connection

即使這段代碼也會對我造成內存泄漏。 我還測試了另一個應用程序(Deleaker),它還告訴我存在相同的內存泄漏。


EDIT2:

只是發現它不是唯一的時間字符串泄漏內存。 這段代碼也是一個問題:

urlString = (string)"http://someurl" + std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(pcName) + (string)"somefile.php";

泄漏的數據恰好是“ urlString”的內容。 我完全感到困惑。

我期望一些未定義的行為。 您已閱讀1024個字符以進行回復。 然后,您使用構造函數,期望以空字符結尾的字符序列。 您如何確定回復是空終止的字符序列?

作為快速測試,請嘗試在此處讀取1023個字符而不是1024個字符:

if (recv(sConnection, reply, 1023, 0) == SOCKET_ERROR)

從套接字讀取數據時,您不應假定一次讀取就已收到所有數據。

在這種情況下,服務器可能已發送了1024個以上的字節,而您恰好讀取了1024個字節。此處可能發生的情況是您的緩沖區將不會以NULL終止,並且您嘗試使用它初始化一個字符串,而沒有給出適當的長度。 Afaik,這是未定義的行為,因此這是您可能要修復的第一件事。 另外,您應該讀取服務器發送的所有數據。

char reply[1025];
ZeroMemory(reply, 1025);
string returnString;
int val = 0;
do 
{
    val = recv(sConnection, reply, 1024, 0);
    if (val == SOCKET_ERROR)
    {
        // Treat errors
    }
    strcat (returnString, reply);
    ZeroMemory(reply, 1025);
}
while (val == 1024); 

編輯 :此代碼是錯誤的。 如果不與服務器進行消息的預先交換,則很難說出消息應包含多少字節或內容。 在此代碼的情況下,如果服務器發送的地址恰好是1024個字節,則在下一次迭代中將阻止recv因為將沒有任何內容可讀取。 網絡協議建立了這些基本的通信規則。 例如,http協議指出消息的第一部分由標頭組成,每個標頭以CRLF對結尾,標頭的末尾由2個CRLF對標記。 為了使我的代碼正確,我將必須解析標頭並提取Content-Length值,然后讀取消息正文,直到達到指定的長度。

此代碼包含潛在的緩沖區溢出,應使用字符串構造函數:

string returnString(reply, 1024);

您使用的構造函數假定正在傳遞一個以null終止的字符串,根據recv()的結果,情況可能並非如此。

編輯:closesocket的返回值是多少? 您確定在程序終止之前實際上已經關閉了套接字嗎? 如果在closesocket調用和結束函數之間等待幾秒鍾會發生什么?

最好遵循MSDN的一些示例代碼,即:

https://msdn.microsoft.com/pl-pl/library/windows/desktop/ms737591(v=vs.85).aspx

或至少嘗試運行此示例以檢查它是否還會對您產生泄漏。

我看到您丟失了關閉調用,是否可能導致泄漏-我不確定,從其文檔中可以看到:

為了確保所有數據在關閉之前在連接的套接字上發送和接收,應用程序應在調用closesocket之前使用shutdown關閉連接。

順便說一句。 使用Win API時,請始終檢查api函數可能返回的所有錯誤代碼。

暫無
暫無

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

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