2014-10-20 3 views
5

Я добавил функцию мини-ядра-дампа (через __try/__ except и MiniDumpWriteDump()) в сборку Windows моего приложения Qt, так что, если/когда мое приложение когда-либо сбой, будет выписан файл .dmp на диск для меня, чтобы посмотреть и отладить с позже.Каков наилучший способ умышленного сбоя моего приложения Windows?

Это работает очень хорошо, но для тестирования я хотел бы иметь известный и надежный метод для сбоя моей программы. Например, в графическом интерфейсе может быть кнопка «сбой сейчас», и когда пользователь нажимает на нее, это приведет к непреднамеренному сбою приложения.

Один из способов сделать это, конечно же, как это:

int * badPointer = NULL; 
*badPointer = 666; 

И это работает для меня, но мне не нравится такой подход, поскольку он опирается на неопределенное поведение - в частности, Стандарт C++ не требует приведенного выше кода, чтобы вызвать сбой, поэтому возможно (с точки зрения юриста), что некоторая будущая версия компилятора не будет сбой при выполнении вышеуказанного кода.

В более «официальной» подход, я попытался это:

abort(); 

... который не прекращает программу, но она не вызывает Structured Exception Windows, который запускает обработчик MiniCrashDump, поэтому нет Файл .dmp записывается.

Мой вопрос: есть ли «официальный правильный путь», чтобы разрушить мою программу? Я вижу, что в Windows API есть функция RaiseException(), которую я мог бы назвать, но я не уверен, какими должны быть правильные аргументы. Это путь, или есть еще какой-то конкретный призыв, который мне лучше использовать?

+0

Молоток через экран. –

+1

Вы используете ключевые слова и поведение, специфичные для реализации, и вы беспокоитесь о том, что спецификация C++ может сказать об этом в какой-то день? Конечно, RaiseException() является официальным способом. –

+0

@HansPassant Это не спецификация C++, которая беспокоит меня так же, как оптимизатор MSVC, который может начать делать умственные трюки в стиле gcc, например, «поскольку я знаю, что badPointer имеет значение NULL, и поскольку разыменование указателя NULL является неопределенным поведением, я могу оптимизируйте прочь, напишите «... и вдруг моя крутая кнопка больше не разбивается. :) –

ответ

3

Совершенно нормально разыменовать нулевой указатель, чтобы вызвать нарушение прав доступа, если вы знаете, что работаете в Windows. Windows обеспечивает более надежные гарантии, чем язык C++. C++ говорит, что разыменование нулевого указателя - это неопределенное поведение, но Windows определяет это как нарушение прав доступа (что вполне приемлемо, поскольку C++ болен, поскольку нарушение доступа является одним из возможных результатов Undefined Behavior).

От Managing Virtual Memory:

Windows NT создает гарантию в адресное пространство каждого процесса. И верхний, и нижний 65 536 байт каждого процесса постоянно зарезервированы системой. Эти части адресного пространства зарезервированы для улавливания шальных указателей указателей, которые пытаются адресовать память в диапазоне 00000000 -0000FFFF или 7FFF0000 -7FFFFFFF . Не случайно, что в этом диапазоне легко обнаружить указатели, просто игнорируя нижние четыре полубайта (самые правые два байта) в этих адресах. По существу, указатель недействителен, если верхние четыре полубайта 0000 или 7FFF ; все остальные значения представляют собой действительные адреса.

Первая страница памяти всегда отображаются в PAGE_NOACCESS, так что если вы попытаетесь прочитать или записать пустой указатель (или любой указатель в пределах +/- 64 КБ нулевого указателя), вы всегда будете поднимать исключение нарушения доступа.

Смежные вопросы