【问题标题】:Handle leaking in WinAPI CreateFile?处理 WinAPI CreateFile 中的泄漏?
【发布时间】:2010-10-06 12:12:12
【问题描述】:

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);
关闭句柄(m_driveHandle);

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

更新。驱动器名称没有剪切和粘贴。正确的字符串是 L"\\.\E:"。错误仍然存​​在。

更新2。问题解决了!看看我下面的答案(欧米茄)。

【问题讨论】:

  • 你是如何确认一开始就是泄密的?
  • 是的,我们禁用了可能的包装软件,包括防病毒软件和 nero(但不会卸载它,嗯...)
  • 在 TaskManager、ProcessExplorer 等中检测到泄漏。
  • 通过CreateFile、CloseHandle反复打开和关闭文件会不会出现这种情况?
  • 您的代码中的错误比 Microsoft 的代码中的错误更大(尽管一切皆有可能)。请显示更多代码,以便我们为您查找问题。

标签: c++ winapi cd-burning


【解决方案1】:

您的示例代码中似乎存在一些错误。如果它实际上是从您的程序中复制和粘贴的,那么肯定会发生其他事情。

首先,您正在调用带有 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 按预期增加。

【讨论】:

  • It was'nt Cut&Paste :) 驱动器名称字符串没问题,我现在将编辑消息中的文本。
  • 我在上面写的示例程序在你编译时是否会泄漏处理?还是第一行打开的句柄数等于最后一行打开的句柄数?
【解决方案2】:

问题出在卡巴斯基防病毒软件中。 KAV 6.0 安装在所有测试机器上。删除软件后需要清除注册表中 cd-driver 的 UpperFilters 和 LowerFilters:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class{4D36E965-E325-11CE-BFC1-08002BE10318}

只有在这个步骤之后,句柄才会停止泄漏.. 该软件的最新版本 Kaspersky Internet Security 也可以正常运行而不会泄露。

【讨论】:

    【解决方案3】:

    建议:
    将日志从调用 CreateFileW 开始,这会确认执行了多少次;

    【讨论】:

    • 这是一个清晰的示例程序,一个用于createFile的字符串,一个用于关闭句柄的字符串。
    • 你检查一下 Jason Owen 所说的关于字符串 L"\\\\.\\E:" 吗?
    【解决方案4】:

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

    【讨论】:

    • 我尝试了 sysinternal 的 russinovich 的工具 ProcessExplorer。这里也有 2 个句柄,它将两个句柄显示为两个内核对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-01
    • 2015-06-15
    • 2015-06-14
    • 1970-01-01
    • 2020-02-29
    • 1970-01-01
    • 2011-12-12
    相关资源
    最近更新 更多