Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: TrevorОтветов: 5

Это необычный вопрос, но вот:

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

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

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

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

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

  • Мне нравится название этого вопроса... но я не могу возможно отправить его без ошибок!! 07.01.2011
  • Вы, кажется, предоставили все, кроме кода. Возможно, компилятор оптимизирует код, который ничего не делает. Ian Boyd 07.01.2011
  • Я полагаю, что исключение обрабатывается где-то? EboMike 07.01.2011
  • Я с EboMike, что-то будет ловить AV David Heffernan 07.01.2011
  • В зависимости от контекста - обычно любое такое действие приводит к ошибке ошибки страницы, поскольку вы не можете прочитать 0x00000000 (или около того). Этот бросок будет распространяться вверх по стеку к любому обработчику, который его примет. Нет обработчика -> обратно в ОС/систему выполнения, которая, вообще говоря, выгружает вызывающий нарушение .exe и завершает процесс. В этой цепочке масса возможностей перехватить такое поведение, не зная вашего контекста, не могу сказать, что именно может ходатайствовать от вашего имени. Mordachai 07.01.2011
  • Ян: Я могу подключить отладчик и выполнить код до того места, где должен произойти segfault. Когда я перехожу к следующей строке, он просто возвращает управление обратно в приложение. Trevor 07.01.2011

c++odbcsegmentation-faultwindows-7

Ответы

Ответ 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 была бы столь же схематичной.

Ответ 2 · рейтинг 18 · Gene Bushuyev

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

Ответ 3 · рейтинг 3 · Петър Петров

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

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

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

Ответ 4 · рейтинг 2 · user541686

Прочтите о различных типах обработчиков исключений здесь. ловить одинаковые исключения.

Ответ 5 · рейтинг 1 · Greg Domjan

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

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

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы