Почему мой код не будет работать в 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 странно или так плохо, как они зависают и никогда не возвращаются.