LoadLibrary()失败,错误8(ERROR_NOT_ENOUGH_MEMORY)

时间:2014-09-25 20:43:40

标签: windows winapi out-of-memory virtual-memory virtual-address-space

稍后编辑:经过更多调查后,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 Update 并注意到一些故障(例如何时 调整窗口大小),但我的程序仍然可以正常工作。刚才我 重新启动,Windows安装了1个更新,我没有过去 ChoosePixelFormat()了。但是,上次安装的更新是 KB2998527,俄罗斯时区更新?!

我已经检查过的事情:

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

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

系统数据转储:Windows 7旗舰版SP1 x64,4GB内存;惠普EliteBook 8470p; Python 3.3,wxPython 3.0.1.dev76673 msw(phoenix);通过SIP 4.15.4访问C ++数据结构;使用Visual Studio 2010 Express编译的C ++代码,使用/MDd进行调试构建。

1 个答案:

答案 0 :(得分:4)

我的虚拟地址空间不足。

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

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

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

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

使用Windows SysInternals工具VMMapdocumentation link)可以轻松地

诊断,它可以显示代码占用了多少进程的虚拟地址空间/ heap / stack / mapped files / shareable data / etc.

这应首先检查LoadLibrary()CreateFileMapping()是否因{1}而失败。