[英]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.