Почему мой код не работает в Windows 7? - PullRequest
14 голосов
/ 07 января 2011

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

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

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

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

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

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

Ответы [ 5 ]

42 голосов
/ 07 января 2011

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

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

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

Обновление:

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

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

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

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

18 голосов
/ 07 января 2011

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

2 голосов
/ 20 апреля 2011

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

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

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

2 голосов
/ 07 января 2011

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

1 голос
/ 08 января 2011

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

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

...