当我为正在测试的进程启用页面堆时,它会触发访问冲突,这表明在调用 SHGetFileInfo 时发生了某种类型的堆损坏。
调用堆栈的顶部显示 msvcr90!wcspbrk 并向下显示 ole32 中与 COM 相关的项目,直到到达 shell32,我们调用 SHGetFileInfo。
从我在网上发现的情况来看,使用 shell32 的一个常见问题是没有首先调用 CoInitialize/CoInitializeEx,但此时已经调用了 CoInitializeEx(),并且在下面的代码之前立即调用它只会返回 S_FALSE。
下面的代码在我们的 DLL 中,它是从 .NET 调用的(代码用于检索用于特定文件的图标):
SHFILEINFOW shfi;
memset(&shfi,0,sizeof(shfi));
SHGetFileInfoW(A2W("C:\\logfile.txt"),
FILE_ATTRIBUTE_NORMAL,
&shfi,
sizeof(shfi),
SHGFI_USEFILEATTRIBUTES
| SHGFI_ICON
);
(其中 logfile.txt 是我根驱动器上的随机文本文件)
为简单起见,我已将第一个参数硬编码到我机器上的文件中。
我使用的是 64 位 Windows 操作系统,但代码在 32 位上下文中运行。如果我使用 SHGetFileInfo 的窄版本,我会得到相同的结果。
如果我为我的进程禁用页面堆,则没有问题。
当我不使用标志 SHGFI_ICON 时,问题不会发生。
编辑:@HansPassant 要求我添加一个可复制的示例,这是一个指向 Visual Studio 2010 Win32 控制台应用程序的链接,演示了该问题:示例