OpenGL подавляет исключения в диалоговом приложении MFC - PullRequest
5 голосов
/ 29 января 2010

У меня есть диалоговое приложение на основе MFC, созданное с помощью MSVS2005.Вот моя проблема шаг за шагом.У меня есть кнопка в моем диалоговом окне и соответствующий обработчик кликов с кодом, подобным следующему:

int* i = 0;
*i = 3;

Я запускаю отладочную версию программы, и когда я нажимаю на кнопку, Visual Studio ловит фокус и выдает предупреждение "Нарушение доступаисключение места записи, программа не может восстановиться после ошибки, и все, что я могу сделать, это остановить отладку.И это правильное поведение.

Теперь я добавляю код инициализации OpenGL в методе OnInitDialog():

    HDC DC = GetDC(GetSafeHwnd());
    static PIXELFORMATDESCRIPTOR pfd =
    {
      sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
      1, // version number
      PFD_DRAW_TO_WINDOW | // support window
      PFD_SUPPORT_OPENGL | // support OpenGL
      PFD_DOUBLEBUFFER, // double buffered
      PFD_TYPE_RGBA, // RGBA type
      24, // 24-bit color depth
      0, 0, 0, 0, 0, 0, // color bits ignored
      0, // no alpha buffer
      0, // shift bit ignored
      0, // no accumulation buffer
      0, 0, 0, 0, // accum bits ignored
      32, // 32-bit z-buffer
      0, // no stencil buffer
      0, // no auxiliary buffer
      PFD_MAIN_PLANE, // main layer
      0, // reserved
      0, 0, 0 // layer masks ignored
    };

    int pixelformat = ChoosePixelFormat(DC, &pfd);
    SetPixelFormat(DC, pixelformat, &pfd);

    HGLRC hrc = wglCreateContext(DC);
    ASSERT(hrc != NULL);
    wglMakeCurrent(DC, hrc);

Конечно, это не совсем то, что я делаю, это упрощенноеверсия моего кода.Что ж, теперь начинают происходить странные вещи: все инициализации в порядке, в OnInitDialog() ошибок нет, но когда я нажимаю кнопку ..., исключение не выдается.Ничего не произошло.Совсем.Если я установлю точку останова на *i = 3; и нажму на нее F11, функция-обработчик немедленно остановится, и фокус вернется к приложению, которое продолжает работать хорошо.Я могу снова нажать кнопку, и произойдет то же самое.

Похоже, что кто-то обработал возникшее исключение из-за нарушения прав доступа и тихо вернул выполнение в основной цикл приема сообщений приложения.

Если я прокомментирую строку wglMakeCurrent(DC, hrc);, все будет работать как и прежде,генерируется исключение, и Visual Studio перехватывает его и показывает окно с сообщением об ошибке, после чего программа должна быть прервана.

Я сталкиваюсь с этой проблемой в Windows 7 64-bit, NVIDIA GeForce 8800 с последними драйверами (от 11.01.2010)доступно на сайте установлен.У моего коллеги 32-разрядная ОС Windows Vista и такой проблемы нет - исключение выдается, и в обоих случаях происходит сбой приложения.

Что ж, надеюсь, хорошие парни помогут мне:)

PS Проблема изначальногде размещено под этой темой.

Ответы [ 5 ]

3 голосов
/ 18 февраля 2010

Хорошо, я узнал еще кое-что об этом. В моем случае это Windows 7, которая устанавливает KiUserCallbackExceptionHandler в качестве обработчика исключений, прежде чем вызвать мой WndProc и дать мне контроль выполнения. Это делается ntdll! KiUserCallbackDispatcher . Я подозреваю, что это мера безопасности, предпринятая Microsoft для предотвращения взлома SEH.

Решение состоит в том, чтобы обернуть ваш wndproc (или hookproc) фреймом try / Кроме того, чтобы вы могли перехватить исключение раньше, чем Windows.

Благодаря Skywing на http://www.nynaeve.net/

Мы связались с nVidia по этому поводу. вопрос, но они говорят, что это не их ошибка, а точнее Microsoft. Мог расскажите пожалуйста как вы нашли обработчик исключений? А у вас есть некоторая дополнительная информация, например немного отзывы от Microsoft?

Я использовал команду! Exchain в WinDbg для получения этой информации.

1 голос
/ 14 апреля 2010

Вместо того, чтобы оборачивать WndProc или перехватывать все WndProcs, вы можете использовать Vectored Exception Handling:

http://msdn.microsoft.com/en-us/library/ms679274.aspx

0 голосов
/ 11 января 2012

Я нашел этот вопрос, когда смотрел на похожую проблему. Нашей проблемой оказалось молчаливое потребление исключений при запуске 32-разрядного приложения в 64-разрядной Windows.

http://connect.microsoft.com/VisualStudio/feedback/details/550944/hardware-exceptions-on-x64-machines-are-silently-caught-in-wndproc-messages

Существует исправление, доступное от Microsoft, хотя его развертывание несколько сложное, если у вас несколько целевых платформ:

http://support.microsoft.com/kb/976038

Вот статья на тему, описывающая поведение:

http://blog.paulbetts.org/index.php/2010/07/20/the-case-of-the-disappearing-onload-exception-user-mode-callback-exceptions-in-x64/

Этот поток переполнения стека также описывает проблему, с которой я столкнулся: Исключения, тихо перехваченные Windows, как обрабатывать вручную?

0 голосов
/ 02 февраля 2011

У меня было похожее поведение (драйвер nVidia установил векторный обработчик исключений, который в конечном итоге приводит к сбою), см .: https://stackoverflow.com/questions/4876796/why-does-an-exception-handled-by-nvidias-opengl-driver-in-copydown-memmove-late

Он пропал при установке последней версии драйвера nVidia (январь 2011 г.).

0 голосов
/ 15 февраля 2010

Во-первых, оба поведения верны. Разыменование нулевого указателя является «неопределенным поведением», а не гарантированным нарушением доступа.

Сначала выясните, связано ли это с выдачей исключений или только с доступом к нулевой ячейке памяти (попробуйте другое исключение).

Если вы настраиваете Visual Studio для остановки при нарушениях прав доступа при первом обращении, происходит ли сбой?

Вызовите VirtualQuery (NULL, ...) до и после glMakeCurrent и сравните. Возможно, nVidia OpenGL драйверы VirtualAlloc страница ноль (плохая идея, но не невозможно или незаконно).

...