64-битные исключения в WndProc молча терпят неудачу - PullRequest
7 голосов
/ 13 апреля 2010

Следующий код приведет к серьезному сбою при работе в Windows 7 32bit:

void CTestView::OnDraw(CDC* /*pDC*/)
{
    *(int*)0 = 0; // Crash

    CTestDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)
        return;

    // TODO: add draw code for native data here
}

Однако, если я попробую это на Windows 7 64bit, я просто получу это в окне вывода:

Исключение первого шанса в 0x13929384 в Test.exe: 0xC0000005: доступ нарушение письменного местоположения 0x00000000.
Исключение первого шанса в 0x77c6ee42 в Test.exe: 0xC0150010: контекст активации деактивирован не активен для текущего потока исполнения.

В чем причина этого? Я знаю, что это аппаратное исключение (http://msdn.microsoft.com/en-us/library/aa363082.aspx),, но почему разница при работе под 32-битной и 64-битной? И что я могу сделать, чтобы правильно обрабатывать ошибки такого рода? Потому что они действительно должны быть перехвачены и исправлены, в отличие от того, что в настоящее время происходит то, что Windows просто передает сообщения приложению и запускает его (поэтому пользователь и разработчики совершенно не знают, что проблемы действительно возникли).

Обновление: Наше обычное программное обеспечение для отчетов о сбоях использует SetUnhandledExceptionFilter, но оно не вызывается на x64 для аппаратных исключений внутри WndProc. У кого-нибудь есть информация по этому поводу или обходной путь?

Update2: Я сообщил о проблеме в Microsoft Connect:
https://connect.microsoft.com/VisualStudio/feedback/details/550944/hardware-exceptions-on-x64-machines-are-silently-caught-in-wndproc-messages

Ответы [ 5 ]

3 голосов
/ 13 апреля 2010

Существует еще одно исключение, возникающее при отмене стека для исключения нарушения прав доступа Который проглатывается, в результате чего AV исчезают. Вам нужно будет выяснить, какой код это делает. Отладка + Исключения, установите флажок Брошенный для Исключений Win32. Отладчик остановится на первом, продолжите. Проверьте стек вызовов, когда он снова остановится. Добавьте это к своему вопросу, если вы не можете понять это.

1 голос
/ 14 июля 2010

ОК, я получил ответ от Microsoft:

Здравствуйте,

Спасибо за отчет. Я узнал что это проблема Windows, и доступно исправление. пожалуйста увидеть http://support.microsoft.com/kb/976038 для исправления, которое вы можете установить, если вы хочу.

@ Skute: обратите внимание, что Программа Помощник по совместимости попросит один раз если программа должна быть разрешена продолжать выполнять, и после этого это всегда будет разрешено, так что может быть причина запутанного поведения вы видите.

Пэт Бреннер Visual C ++ Библиотеки Развитие

Таким образом, чтобы обойти это, убедитесь, что исправление установлено, или оберните каждый WndProc в вашем приложении блоком __try / __except.

0 голосов
/ 26 июня 2013

Я сделал домашнее задание, чтобы найти это: Исключение составляют окна. Вот стеки и разборка:

stack and disassembling when wndproc get called

0 голосов
/ 09 декабря 2010

Я бы рискнул предположить, что проблема на самом деле связана с тем, как SEH работает в x64. Если ваше исключение должно вернуться в режим ядра, когда стек разматывается, то вы застряли в поведении по схеме: Случай исчезновения исключения OnLoad . Windows "обрабатывает" ваше исключение для вас; исправление - это обходной путь, приводящий к аварийному завершению работы определенных приложений x64, как это делает x86.

0 голосов
/ 11 июля 2010

Единственный способ, которым нам удалось обойти эту проблему, - поместить __try / __except вокруг каждого обратного вызова WndProc в приложении. Затем мы направляем исключение в наш обработчик исключений. Ужасно, но похоже, что это проблема самой Windows. Все еще жду, когда Microsoft вернется к нам.

...