Это необычный вопрос, но вот:
В моем коде я где-то случайно разыменовываю NULL. Но вместо сбоя приложения из-за segfault оно, кажется, останавливает выполнение текущей функции и просто возвращает управление пользовательскому интерфейсу. Это затрудняет отладку, потому что обычно я хотел бы получать предупреждения о сбое, чтобы я мог подключить отладчик.
Что может быть причиной этого?
В частности, мой код представляет собой драйвер ODBC (т.е. DLL). Мое тестовое приложение - ODBC Test (odbct32w.exe), которое позволяет мне явно вызывать функции ODBC API в моей библиотеке DLL. Когда я вызываю одну из функций с известным segfault, вместо сбоя приложения ODBC Test просто возвращает управление пользовательскому интерфейсу, не печатая результат вызова функции. Затем я могу снова вызвать любую функцию в моем драйвере.
Я знаю, что технически приложение вызывает диспетчер драйверов ODBC, который загружает и вызывает функции в моем драйвере. Но это не имеет значения, так как мой segfault (или что-то еще) приводит к тому, что функция диспетчера драйверов также не возвращается (о чем свидетельствует приложение, не печатающее результат).
Один из моих коллег с похожей машиной испытывает ту же проблему, а другой - нет, но мы не смогли определить каких-либо конкретных различий.
Ответ 1 · рейтинг 43 · asveikau
Windows имеет непереносимые языковые расширения (известные как "SEH "), которые позволяют отлавливать ошибки страниц и нарушения сегментации как исключения.
Есть части библиотек ОС (особенно внутри кода ОС, который обрабатывает некоторые оконные сообщения, если я правильно помню), которые имеют блок __try и заставят ваш код продолжать работать даже перед лицом таких катастрофических ошибок. Вероятно, вас вызывают внутри одного из этих __try блоков. Грустно, но верно.
Посмотрите этот пост в блоге, например: mode-callback-exceptions-in-x64/" rel="noreferrer">Случай исчезновения исключения OnLoad - исключения обратного вызова пользовательского режима в x64
Обновление:
Я нахожу странными те идеи, которые мне приписывают в комментариях. Для записи:
Я не утверждал, что SEH плохой.
Я сказал, что он "непереносимый", и это правда. Я также утверждал, что использование SEH для игнорирования STATUS_ACCESS_VIOLATION в коде пользовательского режима "печально". Я придерживаюсь этого. Я должен надеяться, что у меня хватило наглости сделать это в новом коде, а вы, просматривая мой код, накричали бы на меня, как если бы я написал catch (...) { /* Ignore this! */ }. Это плохая идея. Это особенно плохо для нарушения доступа, потому что получение AV обычно означает, что ваш процесс находится в плохом состоянии, и вам не следует продолжать выполнение.
Я не утверждал, что существование SEH означает, что вы должны проглатывать все ошибки.
Конечно, SEH - это общий механизм, и его нельзя винить в каждом идиотском его использовании. Я сказал, что некоторые двоичные файлы Windows поглощают STATUS_ACCESS_VIOLATION при вызове указателя на функцию, что является истинным и наблюдаемым фактом, и что это далеко не красиво. Обратите внимание, что у них могут быть исторические причины или смягчающие обстоятельства, оправдывающие это. Отсюда "грустно, но факт".
Я не вводил здесь какую-либо риторику "Windows против Unix". Плохая идея - это плохая идея на любой платформе. Попытка восстановиться с SIGSEGV на ОС типа Unix была бы столь же схематичной.
Ответ 5 · рейтинг 1 · Greg Domjan
Прикрепите свой отладчик ко всем приложениям, которые могут вызывать вашу dll, включите функцию прерывания при возникновении исключения, а не просто необработанного в меню [отладка]|[исключения].
ODBC - это большинство (если не все) COM, поскольку такие необработанные исключения будут вызывать проблемы, которые могут выглядеть как выход из функции ODBC странным образом или так плохо, как зависание и никогда не возвращаются.