Я пытался отладить утечку памяти в моей программе, и сузил ее до связи WinHttp. Я смог воспроизвести проблему в следующем тестовом коде:
#include <windows.h>
#include "winhttp.h"
void main() {
while (1) {
HINTERNET send_session = WinHttpOpen(L"asdf", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
WinHttpCloseHandle(send_session);
}
}
После запуска в течение нескольких секунд программа уже использует более 20 МБ памяти. Почему он это делает? API заявляет, что вам нужно вызвать WinHttpCloseHandle после того, как дескриптор больше не нужен — я делаю это.
Я компилирую с использованием mingw32 в Arch Linux и запускаю код в Windows 7.
Если вы немного измените код, вы увидите, что происходит.
int _tmain(int argc, _TCHAR* argv[])
{
for(INT n = 0; n < 1000000; n++)
{
if(!(n % 10000))
_tprintf(_T("%d\n"), n / 10000);
HINTERNET send_session = WinHttpOpen(L"asdf", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
WinHttpCloseHandle(send_session);
}
_tprintf(_T("Done\n"));
Sleep(INFINITE);
return 0;
}
Наряду с созданием / закрытием миллиона сессий вы увидите, что счетчики растут. API создает фоновые ресурсы, включая потоки, и не освобождает их немедленно, поэтому они продолжают накапливаться.
Однако, как только вы прекратите создавать новые сеансы и дадите им несколько секунд простоя — вы увидите, что вся эта память освобождается.
Суть в том, что в реальном коде не следует создавать отдельный сеанс для каждой мелочи. Один сеанс может содержать несколько соединений и запросов.
Других решений пока нет …