处理WinAPI CreateFile中的泄漏?

时间:2009-02-09 21:04:06

标签: c++ winapi cd-burning

CreateFile分配2(!!)个句柄,而CloseHandle在尝试获取对cd-rom设备的低级访问时仅关闭一个句柄。操作系统Windows XP SP3,经过测试的7台计算机中的5台工作原理相同。

当尝试访问硬盘驱动器盘符时,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);

可能的原因是什么,或者只是一个微软的错误?

UPD。驱动器名称没有被剪切和粘贴..正确的字符串是L“\\。\ E:”。 Bug仍然存在。

UPD2。问题解决了!请参阅下面的答案(欧米茄)。

4 个答案:

答案 0 :(得分:3)

您的示例代码中似乎存在一些错误。如果它实际上是副本&从你的程序粘贴,然后将有其他事情发生。

首先,您正在使用MBCS字符串调用Unicode函数:第一个参数应该在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按预期增加。

答案 1 :(得分:2)

问题出在卡巴斯基反病毒软件中。在所有测试的机器上安装了KAV 6.0。删除软件后,需要清除注册表中CD驱动程序的UpperFilters和LowerFilters:

HKEY_LOCAL_MACHINE \ SYSTEM \ CURRENTCONTROLSET \控制\类{4D36E965-E325-11CE-BFC1-08002BE10318}

只有在此步骤处理后才会停止泄漏.. 最新版本的软件卡巴斯基互联网安全软件也可以在不泄漏的情况下运行。

答案 2 :(得分:0)

建议:
将日志开始于调用CreateFileW,这将确认执行的次数;

答案 3 :(得分:0)

您是否尝试过SysInternals的“处理”工具?它可以显示程序打开的每个句柄,而不仅仅是计数。因此,您将知道哪个句柄保持打开状态。