Почему мой код не будет работать в Windows 7?

Это необычный вопрос, который нужно задать, но здесь:

В моем коде я случайно где-то разыменовал NULL. Но вместо того, чтобы сбой приложения с segfault, он, похоже, прекратил выполнение текущей функции и просто вернул управление обратно в пользовательский интерфейс. Это затрудняет отладку, потому что я обычно хотел бы быть предупрежден о сбое, поэтому я могу подключить отладчик.

Что может быть причиной этого?

В частности, мой код - это драйвер ODBC (т.е. DLL). Моим тестовым приложением является ODBC Test (odbct32w.exe), который позволяет мне явно вызывать функции ODBC API в моей DLL. Когда я вызываю одну из функций, которая имеет известный segfault, вместо сбоя приложения, ODBC Test просто возвращает управление пользовательскому интерфейсу без печати результата вызова функции. Затем я могу снова вызвать любую функцию в моем драйвере.

Я знаю, что технически приложение вызывает диспетчера драйверов ODBC, который загружает и вызывает функции в моем драйвере. Но это не так, поскольку мой segfault (или что-то еще происходит) заставляет функцию диспетчера драйверов не возвращаться (как видно из приложения, не печатающего результат).

Один из моих коллег с аналогичной машиной испытывает эту же проблему, а другой нет, но мы не смогли определить каких-либо конкретных различий.

Ответы

Ответ 1

Windows имеет непереносимые языковые расширения (известные как "SEH" ), которые позволяют обнаруживать ошибки страниц и нарушения сегментации в качестве исключений.

Есть части библиотек ОС (особенно внутри кода ОС, который обрабатывает некоторые оконные сообщения, если я правильно помню), которые имеют блок __try, и заставят ваш код продолжать работать даже перед лицом таких катастрофических ошибок, Вероятно, вы вызываетесь внутри одного из этих блоков __try. Грустно, но это правда.

Отметьте это сообщение в блоге, например: Случай исчезновения исключения OnLoad - исключения обратного вызова пользовательского режима в x64

Update:

Мне кажется, что это странные идеи, которые приписываются мне в комментариях. Для записи:

  • Я сделал not утверждение, что сам SEH плохой.

    Я сказал, что это "не переносимый", что верно. Я также утверждал, что использование SEH для игнорирования STATUS_ACCESS_VIOLATION в коде пользовательского режима "грустно". Я поддерживаю это. Я должен надеяться, что у меня хватило смелости сделать это в новом коде, и вы просмотрели мой код, который вы будете кричать на меня, точно так же, как если бы я написал catch (...) { /* Ignore this! */ }. Это плохая идея. Это особенно плохо для нарушения прав доступа, потому что получение AV обычно означает, что ваш процесс находится в плохом состоянии, и вы не должны продолжать выполнение.

  • Я не утверждал not, что существование SEH означает, что вы должны усвоить все ошибки.

    Конечно, SEH является общим механизмом и не виноват в каждое его идиотское использование. Я сказал, что некоторые двоичные файлы Windows проглатывают STATUS_ACCESS_VIOLATION при вызове указателя функции, истинного и наблюдаемого факта и что это меньше, чем красиво. Обратите внимание, что они могут иметь исторические причины или смягчать обстоятельства, чтобы оправдать это. Следовательно, "грустно, но верно".

  • Я сделал not любую риторику "Windows vs. Unix" здесь. Плохая идея - плохая идея на любой платформе. Попытка восстановить с SIGSEGV в ОС Unix-типа будет одинаково отрывочной.

Ответ 2

Указатель NULL разыменования - это поведение undefined, которое может генерировать почти все: seg.fault, письмо IRS или сообщение в stackoverflow:)

Ответ 3

Читайте о различных видах обработчиков исключений здесь - они не улавливают одни и те же исключения.

Ответ 4

В Windows 7 также есть своя Толерантная куча ошибок (FTH), которая иногда делает такие вещи. В моем случае это было также NULL-разыменованием. Если вы разрабатываете Windows 7, вы действительно хотите отключить его!

Что такое отказоустойчивая куча Windows 7?

http://msdn.microsoft.com/en-us/library/dd744764%28v=vs.85%29.aspx

Ответ 5

Прикрепите ваш отладчик ко всем приложениям, которые могут вызывать вашу DLL, включите функцию, чтобы сломать, когда выброс не был обработан не в необработанном меню [debug] | [exceptions].

ODBC - это самый (если не все) COM, поскольку такие необработанные исключения вызовут проблемы, которые могут появляться как выход из функции ODBC странно или так плохо, как они зависают и никогда не возвращаются.