Обрабатывать утечки в 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? Он может показать вам каждый дескриптор, открытый вашей программой, а не только счетчик. Следовательно, вы будете знать, какая ручка остается открытой.

Другие вопросы по тегам