LoadLibrary() 失败并出现错误 8 (ERROR_NOT_ENOUGH_MEMORY)

Posted

技术标签:

【中文标题】LoadLibrary() 失败并出现错误 8 (ERROR_NOT_ENOUGH_MEMORY)【英文标题】:LoadLibrary() fails with error 8 (ERROR_NOT_ENOUGH_MEMORY) 【发布时间】:2014-09-25 20:43:40 【问题描述】:

稍后编辑:经过更多调查,Windows 更新和 OpenGL DLL 是红鲱鱼。这些症状的原因是LoadLibrary() 调用失败并显示GetLastError() == ERROR_NOT_ENOUGH_MEMORY。请参阅我的答案以了解如何解决此类问题。以下是历史兴趣的原始问题。 /编辑

我突然用 Python/wxPython for Windows 编写了一个带有 C++ 后端的地图查看器 停止工作,没有任何代码更改甚至重新编译。一样的 可执行文件已经工作了数周(相同的 Python,相同的 DLL,...)。

现在,当向 Windows 查询要与 OpenGL 一起使用的像素格式时(使用 ChoosePixelFormat()),我得到一个 MessageBox 说:

LoadLibrary failed with error 8:
Not enough storage is available to process this command

执行以下代码片段时显示错误信息:

void DevContext::SetPixelFormat() 
    PIXELFORMATDESCRIPTOR pfd;
    memset(&pfd, 0, sizeof(pfd));
    pfd.nSize        = sizeof(pfd);
    pfd.nVersion     = 1;
    pfd.dwFlags      = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
    pfd.iPixelType   = PFD_TYPE_RGBA;
    pfd.cColorBits   = 32;

    int pf = ChoosePixelFormat(m_hdc, &pfd);    // <-- ERROR OCCURS IN HERE
    if (pf == 0) 
        throw std::runtime_error("No suitable pixel format.");
    

    if (::SetPixelFormat(m_hdc, pf, &pfd) == FALSE) 
        throw std::runtime_error("Cannot set pixel format.");
    

它实际上是一个显示消息框的 ATI GL 驱动程序 DLL。调用堆栈的相关部分是这样的:

                  ... More MessageBox stuff
0027e860 770cfcf1 USER32!MessageBoxTimeoutA+0x76
0027e880 770cfd36 USER32!MessageBoxExA+0x1b
*** ERROR: Symbol file not found. Defaulted to export symbols for C:\Windows\SysWOW64\atiglpxx.dll -
0027e89c 58471df1 USER32!MessageBoxA+0x18
0027e9d4 58472065 atiglpxx+0x1df1
0027e9dc 57acaf0b atiglpxx!DrvValidateVersion+0x13
0027ea00 57acb0f3 OPENGL32!wglSwapMultipleBuffers+0xc5e
0027edf0 57acb1a9 OPENGL32!wglSwapMultipleBuffers+0xe46
0027edf8 57acc6a4 OPENGL32!wglSwapMultipleBuffers+0xefc
0027ee0c 57ad5658 OPENGL32!wglGetProcAddress+0x45f
0027ee28 57ad5dd4 OPENGL32!wglGetPixelFormat+0x70
0027eec8 57ad6559 OPENGL32!wglDescribePixelFormat+0xa2
0027ef48 751c5ac7 OPENGL32!wglChoosePixelFormat+0x3e
0027ef60 57c78491 GDI32!ChoosePixelFormat+0x28
0027f0b0 57c7867a OutdoorMapper!DevContext::SetPixelFormat+0x71 [winwrap.cpp @ 42]
0027f1a0 57ce3120 OutdoorMapper!OGLContext::OGLContext+0x6a [winwrap.cpp @ 61]
0027f224 1e0acdf2 maplib_sip!func_CreateOGLDisplay+0xc0 [maps.sip @ 96]
0027f240 1e0fac79 python33!PyCFunction_Call+0x52
                  ... More Python stuff

两周前我做了 Windows 更新,发现了一些故障(例如,当 调整窗口大小),但我的程序仍然可以正常工作。刚才我 重新启动,Windows 又安装了 1 个更新,但我没有通过 ChoosePixelFormat() 更多。但是,最后安装的更新是 KB2998527,俄罗斯时区更新?!

我已经检查过的事情:

重新编译无法正常工作。 在没有其他程序运行的情况下重新启动和运行不起作用。 我的程序的内存消耗只有 67 MB,我没有内存不足。 大量可用磁盘空间 (~50 GB)。 HDC m_hdc 是从显示面板的HWND 获得的,似乎是有效的。 Changing my linker commandline 不起作用。

我应该更新我的图形驱动程序还是回滚更新?还有其他想法吗?

系统数据转储:Windows 7 Ultimate SP1 x64,4GB RAM; HP EliteBook 8470p; Python 3.3,wxPython 3.0.1.dev76673 msw(凤凰);通过 SIP 4.15.4 访问 C++ 数据结构;使用 Visual Studio 2010 Express 编译的 C++ 代码,使用 /MDd 调试构建。

【问题讨论】:

【参考方案1】:

我的虚拟地址空间用完了。

默认情况下,LibTIFF 通过内存映射来读取 TIF 图像(mmap()CreateFileMapping())。这对于你妻子的照片来说很好,但对于价值千兆字节的阿尔卑斯山地形栅格图来说,这是一个坏主意。

这很难诊断,因为如果内存映射失败,LibTIFF 会默默地退回到read(),因此之前从未出现过显式错误。此外,Windows 不将映射内存计为工作内存,因此任务管理器显示为 67MB,而实际上几乎所有虚拟地址空间都已用完。

因为我最近在我的数据库中添加了更多的 TIF 图像,所以现在这个问题爆发了。 LoadLibrary() 开始失败,因为它找不到任何地址空间来放置新库。 GetLastError() 返回 8,即 ERROR_NOT_ENOUGH_MEMORY。这发生在 ATI 的 OpenGL 库中只是巧合。

解决方案是将"m" 作为标志传递给TiffOpen() 以禁用内存映射IO。

诊断此问题很容易使用 Windows SysInternals 工具VMMap (documentation link),它可以显示代码/堆/堆栈占用了多少进程的虚拟地址空间/映射文件/可共享数据/等。

这应该是检查LoadLibrary()CreateFileMapping() 是否以ERROR_NOT_ENOUGH_MEMORY 失败的第一件事。

【讨论】:

处理非常大的图像集时,我建议使用 Vips:vips.ecs.soton.ac.uk/index.php?title=VIPS

以上是关于LoadLibrary() 失败并出现错误 8 (ERROR_NOT_ENOUGH_MEMORY)的主要内容,如果未能解决你的问题,请参考以下文章

LoadLibrary 失败,错误代码为 14001

LoadLibrary加载动态库失败

LoadLibrary 失败并显示 lasterror 0x43 找不到网络名称

Qt 4.8.4 Cross-Compiled for Embedded Linux 失败并出现 QNetworkProxy 错误

LAMPP 启动失败并出现错误 2

loadlibrary("dll") 失败-找不到指定的模块