Обрабатывать утечки в WinAPI CreateFile?
CreateFile выделяет 2(!!) дескриптора, а CloseHandle закрывает только один дескриптор при попытке получить низкоуровневый доступ к устройству cd-rom. ОС Windows XP SP3, 5 из 7 протестированных компьютеров работают одинаково.
При попытке доступа к жесткому диску буква CreateFiles работает нормально и выделяет только один дескриптор.
Вот пример кода:
HANDLE m_driveHandle = CreateFileW ("\\\\. \\ E", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);CloseHandle (m_driveHandle);
Какова возможная причина или это просто ошибка Microsoft?
Upd. Имя диска не вырезано и не вставлено. Правая строка - L"\\.\E:". Ошибка все еще сохраняется.
UPD2. Задача решена! Смотрите ответ ниже от меня (омега).
4 ответа
Кажется, в вашем примере кода есть несколько ошибок. Если бы это было на самом деле скопировано и вставлено из вашей программы, то должно было бы быть что-то еще.
Во-первых, вы вызываете функцию Unicode со строкой MBCS: первый аргумент должен начинаться с префикса L
или в окружении _T()
,
Во-вторых, и, возможно, более важно, "\\\\.\\E"
не является действительным именем Вам не хватает конечного двоеточия: для открытия тома он должен иметь форму \\.\X:
или в вашем случае "\\\\.\\E:"
,
После исправления этих двух ошибок (первый мешал компиляции, второй требовал получить что-то кроме INVALID_HANDLE_VALUE
назад) все вроде бы работало как положено. Я использовал GetProcessHandleCount для подсчета количества открытых дескрипторов, и это было одинаково до и после:
HANDLE m_driveHandle = NULL;
HANDLE m_process = GetCurrentProcess();
DWORD handleCount;
GetProcessHandleCount(m_process, &handleCount);
cout << "Currently held handles: " << handleCount << endl;
for (int i = 0; i < 10; ++i) {
m_driveHandle = CreateFileW(L"\\\\.\\E:",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (INVALID_HANDLE_VALUE == m_driveHandle) {
cout << "Invalid handle" << endl;
} else {
CloseHandle(m_driveHandle);
}
GetProcessHandleCount(m_process, &handleCount);
cout << "Currently held handles: " << handleCount << endl;
}
Комментирование вызова CloseHandle также приводит к тому, что handleCount будет увеличиваться, как и ожидалось.
Проблема была в программном обеспечении Антивируса Касперского. KAV 6.0 был установлен на все проверенные машины. После удаления программного обеспечения необходимо очистить UpperFilters и LowerFilters для cd-драйвера в реестре:
HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ Class {4D36E965-E325-11CE-BFC1-08002BE10318}
Только после этого действия дескрипторы перестают вытекать. Последняя версия программного обеспечения, Kaspersky Internet Security, также работает без утечек.
Предложение:
Ставить log begin при вызове CreateFileW, это подтверждает, сколько раз он выполняется;
Вы пробовали инструмент "Ручка" от SysInternals? Он может показать вам каждый дескриптор, открытый вашей программой, а не только счетчик. Следовательно, вы будете знать, какая ручка остается открытой.