LoadLibrary() завершается с ошибкой 8 (ERROR_NOT_ENOUGH_MEMORY)

Позже редактирование: после дополнительных исследований, обновления Windows и OpenGL DLL были красными сельдями. Причиной этих симптомов была LoadLibrary() сбой вызова с GetLastError() == ERROR_NOT_ENOUGH_MEMORY, Смотрите мой ответ о том, как решить такие проблемы. Ниже оригинальный вопрос исторического интереса. /редактировать

Вьюер карт, который я написал в Python/wxPython для 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.");
    }
}

На самом деле это DLL-библиотека драйвера ATI GL, отображающая окно сообщения. Соответствующая часть стека вызовов:

                  ... 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 МБ, мне не хватает памяти.
  • Много свободного дискового пространства (~50 ГБ).
  • HDC m_hdc получается из панели дисплея HWND и кажется действительным.
  • Изменение командной строки моего компоновщика не работает.

Должен ли я обновить мои графические драйверы или откатить обновления? Есть другие идеи?

Системный дамп данных: Windows 7 Ultimate SP1 x64, 4 ГБ ОЗУ; HP EliteBook 8470p; Python 3.3, wxPython 3.0.1.dev76673 msw (феникс); доступ к структурам данных C++ через SIP 4.15.4; Код C++, скомпилированный с Visual Studio 2010 Express, отладка с помощью /MDd,

1 ответ

Решение

У меня заканчивалось виртуальное адресное пространство.

По умолчанию LibTIFF читает изображения TIF, отображая их в памяти (mmap() или же CreateFileMapping()). Это хорошо для фотографий вашей жены, но оказывается, что это плохая идея для гигабайтных топографических растровых карт Альп.

Это было трудно диагностировать, потому что LibTIFF молча отступил к read() если отображение памяти не удалось, то никогда не было явной ошибки раньше. Кроме того, сопоставленная память не учитывается Windows как рабочая память, поэтому диспетчер задач показывал 67 МБ, хотя фактически использовалось почти все виртуальное адресное пространство.

Это взорвалось сейчас, потому что я недавно добавил больше изображений TIF в свою базу данных. LoadLibrary() начал сбой, потому что он не мог найти адресное пространство для размещения новой библиотеки. GetLastError() вернул 8, что ERROR_NOT_ENOUGH_MEMORY, То, что это произошло в библиотеке OpenGL от ATI, было просто совпадением.

Решение было пройти "m" как флаг TiffOpen() отключить память сопоставленного ввода-вывода.

Диагностировать это легко с помощью инструмента Windows SysInternals VMMap ( ссылка на документацию), который показывает, сколько виртуального адресного пространства процесса занимает код / ​​куча / стек / сопоставленные файлы / разделяемые данные / и т. Д.

Это должно быть первым делом, чтобы проверить, если LoadLibrary() или же CreateFileMapping() не удается с ERROR_NOT_ENOUGH_MEMORY,

Другие вопросы по тегам