Какой самый простой способ вызвать сбой программы на C ++?

319

Я пытаюсь создать программу на Python, которая взаимодействует с другим аварийным процессом (это не в моих руках). К сожалению, программа, с которой я взаимодействую, даже не дает сбоя! Поэтому я хочу сделать быструю программу на C ++, которая намеренно зависает, но я на самом деле не знаю лучшего и кратчайшего способа сделать это, кто-нибудь знает, что нужно поместить между моими:

int main() {
    crashyCodeGoesHere();
}

чтобы моя C ++ программа аварийно завершилась

Джонатан Топф
источник
4
Вы можете использовать встроенную сборку, чтобы попытаться выполнить привилегированные инструкции:asm { cli; };
Нейт Коппенхавер
@aitchnyu Я думаю, что есть разница в удобстве ответов на каждый вопрос. (К вашему сведению: я не голосовал ни за один из этих вопросов)
Эндрю Барбер
Есть ли какие-нибудь комментарии по поводу исключения, пока кто-то уже пропагандирует ?? PLZ CHK мой ответ ниже комментарий anc
Abhinav
4
Redis использует следующий *((char*)-1) = 'x';код, чтобы вызвать сбой, чтобы отладить, подробнее в моем ответе здесь
Shafik Yaghmour
Я нашел этот вопрос в поисках тестового примера для системы отчетов о сбоях. Мне нужно было вызвать сбой во время обычной среды выполнения, чтобы вызвать репортер сбоев и отправку дампа стека. Спасибо!
Кори Трезе

Ответы:

265

abort()Функция, вероятно , ваш лучший выбор. Он является частью стандартной библиотеки C и определяется как «вызывающий ненормальное завершение программы» (например, фатальная ошибка или сбой).

сумеречный
источник
14
Обратите внимание, что сбой abort()не вызывает никаких деструкторов или atexitфункций, хотя это, скорее всего, здесь не имеет значения.
Xeo
139
@Xeo: Если бы он вызывал деструкторы и atexits, это не было бы крахом, не так ли?
Donal Fellows
Так abort()как правильный ответ, то должен ли 'exit (-1); `быть приемлемым?
asir6
9
Нет, поскольку это не приводит к сбою, просто сообщает, что что-то не может быть сделано.
кодек
Окна. GCC-5.4.0. Код выхода: 3. Нет сообщения об ошибке. Консольное сообщение: «Это приложение запросило среду выполнения прервать его необычным способом. Для получения дополнительной информации обратитесь в службу поддержки приложения».
Вадим
113

Пытаться:

raise(SIGSEGV);  // simulates a standard crash when access invalid memory
                 // ie anything that can go wrong with pointers.

Нашел в:

#include <signal.h>
Мартин Йорк
источник
3
Это больше, чем просто определение реализации - сигнал можно поймать signal(). Однако большинство нормальных приложений этого не делают.
duskwuff -неактивный-
12
Он будет аварийно завершать работу точно так же, как и обычный SIGSEGV в приложении (именно так происходит сбой большинства приложений). Он четко определил, что он делает (по умолчанию он выходит из приложения и генерирует файл ядра). Да, вы можете установить обработчик, но если он у вас есть, вы не хотите проверять его таким же образом !!
Мартин Йорк
1
+1 за raise(). Это позволяет вам проверять множество различных типов исключений, просто изменяя аргумент.
3
любимое решение, однако оно зависит от платформы.
Надим Фархат
@NadimFarhat: каким образом. Сигнал есть сигнал на всех платформах.
Мартин Йорк
74

Деление на ноль приведет к сбою приложения:

int main()
{
    return 1 / 0;
}
Роуи Гавирель
источник
29
В зависимости от того, насколько умен ваш компилятор, он будет обнаружен во время компиляции. Я знаю, что Visual Studio 2008 не скомпилирует это для c ++ или c #.
AidanO
2
Я скомпилировал и запустил его, вы хотите, чтобы я зашкурил вас .exe?
Роуи Гавирель
1
В конфигурации выпуска в последних версиях Visual Studio, такой как 2010, он будет работать без проблем. Я думаю, это какая-то оптимизация.
Тедью
2
iirc не падает на руку
шерпя
2
Это неопределенное поведение и не гарантируется сбой. Часто компиляторы предполагают, что неопределенное поведение недоступно. Это может привести к тому, что тело mainбудет полностью удалено, включая retинструкцию. Выполнение может просто попасть в следующую функцию.
USR
64
*((unsigned int*)0) = 0xDEAD;
Кит Николас
источник
54
Это не гарантирует сбой.
Windows-программист
8
@Windowsprogrammer: нет, это не гарантировано . Но какая нормальная ОС не останавливает приложение, которое пытается получить доступ к памяти по адресу 0?
Иоахим Зауэр
29
«Но какая нормальная ОС не останавливает приложение, которое пытается получить доступ к памяти по адресу 0?» - Это не совсем то, что вы хотите спросить, но я все равно отвечу. На некоторых компьютерах ОЗУ находится по адресу 0, и для программы очень важно хранить там значения. Более значимым вопросом будет «Какая ОС не останавливает приложение, которое обращается к памяти по адресу, который реализация C ++ зарезервировала для нулевого указателя?» В таком случае я не знаю ни одного. Но оригинальная программа посвящена языку C ++, а не ОС.
Windows программист
6
Его неопределенное поведение. Это нормально для этого ничего не делать. Машина, которая не выйдет из строя: все, что работает под управлением процессора серии Z80 (я полагаю (мой Z80a ничего не делает)).
Мартин Йорк
28
Хотя это не гарантирует сбой, это один из самых распространенных видов сбоя в C ++. Так что, если вы хотите смоделировать аварию, это «подлинный» способ сделать это :)
Крис Бурт-Браун
53

Ну, у нас переполнение стека или нет?

for (long long int i = 0; ++i; (&i)[i] = i);

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

Сэм Хоцевар
источник
4
Я вижу, что это забавно в системе с незащищенными кодовыми страницами, и вы перезаписываете свою программу некоторым кодом, который случайно представляет собой бесконечный цикл, который ничего не делает. Очень, очень, очень, очень маловероятно, но потенциально возможно.
Мартин Йорк
@Loki: Что делать, если он просто читает каждый 4000-й байт? Это будет меньше шансов на крах? Определенно менее опасно.
Mooing Duck
70
Этот алгоритм сбоя не O (1)!
Антон Барковский
@MooingDuck: я просто делаю забавный комментарий. Не принимайте это всерьез :-) Но было бы интересно, если бы кто-нибудь нашел последовательность инструкций, которая сделала бы что-то смешное.
Мартин Йорк
1
@LokiAstari: вы абсолютно правы. Я думал об этом (&i)[i] += !i, но боялся, что компилятор может быть достаточно умным, и хочу оптимизировать это. :-)
Сэм Хоцевар
35
 throw 42;

Просто ответ ... :)

Маке
источник
1
Окна. GCC-5.4.0. Код выхода: 3. Нет сообщения об ошибке. Консольное сообщение: «завершить вызов после выброса экземпляра« int ». Это приложение запросило среду выполнения, чтобы завершить его необычным способом. Для получения дополнительной информации обратитесь в службу поддержки приложения».
Вадим
15

assert(false); тоже довольно хорошо

В соответствии с ISO / IEC 9899: 1999 гарантированно происходит сбой, когда NDEBUG не определен:

Если определен NDEBUG [...], макрос assert определяется просто как

#define assert(ignore) ((void)0)

Макрос assert переопределяется в соответствии с текущим состоянием NDEBUG при каждом включении.

[...]

Макрос assert помещает диагностические тесты в программы; [...] если выражение (которое должно иметь скалярный тип) является ложным [...]. Затем он вызывает функцию прерывания.

Дэн Ф
источник
Я смутно помню, как VC 2005 вел себя по-разному между отладкой и выпуском с утверждениями?
Том Керр
8
@Tom assertсделан эквивалентным ((void)0)в режиме Release.
Сет Карнеги
2
@SethCarnegie Не видите, что с этим не так - только если определенная воля, определенная NDEBUG, не завершится сбоем? Ответ данс был довольно честным ИМХО.
Адриан Корниш
@AdrianCornish Я только отвечал на вопрос Тома Керра, не говоря, что этот ответ был неправильным. Я не понизил этот ответ.
Сет Карнеги
3
Я не знаю, почему он сделал бы «релизную» сборку этого тестового кода.
Джоэл Б
11

Поскольку сбой является признаком вызова неопределенного поведения, и поскольку вызов неопределенного поведения может привести к чему угодно, включая сбой, я не думаю, что вы действительно хотите вывести свою программу из строя, но просто поместите ее в отладчик. Вероятно, самый переносимый способ сделать это abort().

Хотя raise(SIGABRT)имеет тот же эффект, это, безусловно, больше писать. Однако оба способа могут быть перехвачены путем установки обработчика сигнала для SIGABRT. Поэтому, в зависимости от вашей ситуации, вы можете / должны поднять другой сигнал. SIGFPE, SIGILL, SIGINT, SIGTERMИли SIGSEGVможет быть путь, но все они могут быть перехвачены.

Когда вы можете быть непереносимыми, ваш выбор может быть еще шире, как при использовании SIGBUSв Linux.

PlasmaHH
источник
1
Я действительно сомневаюсь, что он хочет задействовать отладчик. Похоже, он хочет проверить, что происходит, когда вызывающий сбой программы получает сообщение о сбое. Что очень разумно.
Донал Феллоуз
9

Единственная вспышка, которая у меня была, это функция abort () :

Он прерывает процесс с ненормальным завершением программы. Он генерирует сигнал SIGABRT , который по умолчанию заставляет программу завершить работу, возвращая неуспешный код ошибки завершения в среду хоста. Программа завершается без выполнения деструкторов для объектов автоматической или статической длительности хранения. и без вызова какой-либо функции atexit (которая вызывается методом exit () до завершения программы). Он никогда не возвращается к своему абоненту.

samridhi
источник
9

Ответ зависит от платформы и зависит от ваших целей. Но вот функция сбоя Mozilla Javascript, которая, я думаю, иллюстрирует множество проблем, которые могут возникнуть при выполнении этой работы:

static JS_NEVER_INLINE void
CrashInJS()
{
    /*
     * We write 123 here so that the machine code for this function is
     * unique. Otherwise the linker, trying to be smart, might use the
     * same code for CrashInJS and for some other function. That
     * messes up the signature in minidumps.
     */

#if defined(WIN32)
    /*
     * We used to call DebugBreak() on Windows, but amazingly, it causes
     * the MSVS 2010 debugger not to be able to recover a call stack.
     */
    *((int *) NULL) = 123;
    exit(3);
#elif defined(__APPLE__)
    /*
     * On Mac OS X, Breakpad ignores signals. Only real Mach exceptions are
     * trapped.
     */
    *((int *) NULL) = 123;  /* To continue from here in GDB: "return" then "continue". */
    raise(SIGABRT);  /* In case above statement gets nixed by the optimizer. */
#else
    raise(SIGABRT);  /* To continue from here in GDB: "signal 0". */
#endif
}
Пол Биггар
источник
2
Вы должны полностью отбросить это и использовать вместо этого jQuery.
Томас Уэллер
1
Это неопределенное поведение и не гарантируется сбой. Часто компиляторы предполагают, что неопределенное поведение недоступно. В этом случае, по крайней мере, строка сбоя будет удалена, и другой код также может быть.
USR
8

Я вижу, что здесь опубликовано много ответов, которые выпадут в удачных случаях, чтобы выполнить работу, но ни один из них не является на 100% детерминированным к краху. Некоторые будут зависать на одном оборудовании и ОС, другие - нет. Тем не менее, существует официальный способ, согласно официальному стандарту C ++, заставить его аварийно завершить работу.

Цитирование из стандарта C ++ ISO / IEC 14882 §15.1-7 :

Если механизм обработки исключений после завершения инициализации объекта исключения, но до активации обработчика исключения, вызывает функцию, которая завершается через исключение, вызывается std :: terminate (15.5.1).

struct C {
    C() { }
    C(const C&) {
        if (std::uncaught_exceptions()) {
            throw 0; // throw during copy to handler’s exception-declaration object (15.3)
        }
    }
};
int main() {
    try {
    throw C(); // calls std::terminate() if construction of the handler’s
    // exception-declaration object is not elided (12.8)
    } catch(C) { }
}

Я написал небольшой код, чтобы продемонстрировать это, и его можно найти и попробовать на Ideone здесь .

class MyClass{
    public:
    ~MyClass() throw(int) { throw 0;}
};

int main() {
  try {
    MyClass myobj; // its destructor will cause an exception

    // This is another exception along with exception due to destructor of myobj and will cause app to terminate
     throw 1;      // It could be some function call which can result in exception.
  }
  catch(...)
  {
    std::cout<<"Exception catched"<<endl;
  }
  return 0;
}

ИСО / МЭК 14882 §15.1 / 9 упоминает throw без блока try, что приводит к неявному вызову abort:

Если никакое исключение в настоящее время не обрабатывается, выполнение выражения броска без операндов вызывает std :: terminate ()

Другие включают: бросок от деструктора: ISO / IEC 14882 §15.2 / 3

Abhinav
источник
7
*( ( char* ) NULL ) = 0;

Это приведет к ошибке сегментации.

wrren
источник
10
Это не гарантирует сбой.
Windows-программист
23
"Что будет вместо этого?" - Вместо этого может произойти все что угодно. Поведение не определено, поэтому реализация может присвоить 0 одной из переменных вашей программы, или она может присвоить 42 одной из переменных вашей программы, или это может отформатировать ваш жесткий диск и продолжить выполнение вашей программы.
Windows-программист
7
(продолжает настроение «программиста Windows»). Это может заставить ваш компьютер взорваться, или это может заставить его ожить и захватить человечество. или ... он падает на 99,9% и определяется как "неопределенное поведение", потому что никто не хочет брать на себя ответственность за это.
Роу Гавирел
1
На самом деле, это не гарантирует даже неопределенное поведение - оно может быть полностью определено и работать правильно. Рассмотрим этот код: pastebin.com/WXCtTiDD (протестировано на Linux как пользователь root, вы также можете сделать это как пользователь без полномочий root, если вы внесете некоторые изменения в конфигурацию wiki.debian.org/mmap_min_addr )
cha0site
2
@ cha0site: Стандартом гарантировано неопределенное поведение, потому что это разыменовывает нулевой указатель. Любое поведение, которое вы наблюдали в Linux, допустимо в рамках «неопределенного поведения»
Бен Фойгт,
6

Этот отсутствует:

int main = 42;
MVDS
источник
1
Да, это так; но это делает что-то впечатляющее, когда вы запускаете это.
Джошуа
5

Как насчет переполнения стека при вызове рекурсивного метода мертвого цикла?

#include <windows.h>
#include <stdio.h>

void main()
{
    StackOverflow(0);
}

void StackOverflow(int depth)
{
    char blockdata[10000];
    printf("Overflow: %d\n", depth);
    StackOverflow(depth+1);
}

См. Оригинальный пример на Microsoft KB

SLL
источник
4
Что помешало бы Достаточно Умному Компилятору оптимизировать как неиспользуемое выделение стека, так и хвостовой вызов?
JB.
@JB: к сожалению, понятия не имею, потому что не знаком с существующей логикой оптимизации компиляторов
sll
8
Ну, скомпилированный здесь с gcc 4.6.0 на уровнях оптимизации -O2 и выше, он оптимизируется просто отлично. Для сегфоута необходимо -O1 или ниже.
JB.
@Abhinav: Просто опубликовать свой ответ со всеми этими способами , выраженных в качестве примеров в C ++ :)
SLL
5

Это происходит сбой в моей системе Linux, потому что строковые литералы хранятся в постоянной памяти:

0[""]--;

Кстати, g ++ отказывается компилировать это. Компиляторы становятся умнее и умнее :)

fredoverflow
источник
4
int i = 1 / 0;

Ваш компилятор, вероятно, предупредит вас об этом, но он прекрасно компилируется в GCC 4.4.3. Это, вероятно, вызовет SIGFPE (исключение с плавающей запятой), что, вероятно, не так вероятно в реальном приложении, как SIGSEGV (нарушение сегментации памяти), как другие ответы вызывают, но это все еще крах. На мой взгляд, это гораздо более читабельно.

Другой способ, если мы собираемся обмануть и использовать signal.h, это:

#include <signal.h>
int main() {
    raise(SIGKILL);
}

Это гарантированно уничтожит подпроцесс, в отличие от SIGSEGV.


источник
2
Это не гарантирует сбой.
Windows программист
11
Язык C ++ не гарантирует, что 1/0 вызовет SIGFPE. Поведение не определено. Реализация могла бы сказать, что результат - 42.
Windows программист
1
Когда поведение не определено, реализация может делать все, что захочет. Язык C ++ не предотвращает и не требует реализации для записи аварийного дампа, язык C ++ не предотвращает и не требует реализации для назначения 42 и т. Д.
Программист Windows
2
@ Джорджио, если на оборудовании нет способа автоматически его перехватить, вы все равно заставляете компиляторы выдавать как минимум две инструкции, одна из которых тоже будет ветвью. Это примерно вдвое превышает стоимость подразделения. Все платят такую ​​цену. Если это необязательно и вы хотите его, вы всегда можете использовать библиотечную функцию для него. Если это не является обязательным, и вы не хотите, вы все равно в конечном итоге оплатить стоимость.
Флексо
2
@Giorgio: У меня есть приложение, которое делает 100 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 Я точно знаю, что 0 из них будет делением на ноль, хотя компилятор не может этого знать. Я определенно не хочу, чтобы компилятор установил проверку деления на ноль.
Мартин Йорк
4

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

#include<stdio.h>
#include<signal.h>
#include<unistd.h> 
#include<stdlib.h>
int main()
{
    sigset_t act;
    sigemptyset(&act);
    sigfillset(&act);
    sigprocmask(SIG_UNBLOCK,&act,NULL);
    abort();
}
Bashrc
источник
3
int* p=0;
*p=0;

Это тоже должно вылететь. В Windows происходит сбой с AccessViolation, и он должен делать то же самое на всех ОС, я думаю.

laci37
источник
5
on all OS-esНет, он не откажет в не защищенной ОС (например , MS-DOS.) На самом деле, иногда это что - то в адрес 0! Для x86 режиме реального времени, вектор прерывания Таблица в адрес 0.
IKH
Это не обрушилось на Ирикса. Я с грустью понял, когда мы портировали этот код в Linux (куда мы даже не дошли main().
Scheff
3

Это фрагмент, предоставленный Google в Breakpad.

  volatile int* a = reinterpret_cast<volatile int*>(NULL);
  *a = 1;
Кори Трез
источник
1
Так как я тестирую Breakpad, это именно то, что я хотел! Я обнаружил, что некоторые мини-дампы Breakpad не генерируют трассировку стека, которая указывает на строку в моем коде, вызывающую сбой. Это делает, так что я могу использовать его как хороший тест Poc.
BuvinJ
2
int main(int argc, char *argv[])
{
    char *buf=NULL;buf[0]=0;
    return 0;
}
Аникет Инге
источник
2

Хотя на этот вопрос уже есть принятый ответ ...

void main(){
    throw 1;
}

Или... void main(){throw 1;}

noɥʇʎԀʎzɐɹƆ
источник
2

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

int main() {
    (int&)main = 0;
}

Я проверил это с MingGW 5.3.0 на Windows 7 и GCC на Linux Mint. Я предполагаю, что другие компиляторы и системы дадут аналогичный эффект.

БЕЗ ИМЕНИ
источник
1

Или другой путь, так как мы в группе.

Прекрасный кусок бесконечной рекурсии. Гарантированно взорвать ваш стек.

int main(int argv, char* argc)
{
   return main(argv, argc)
}

Распечатывает:

Ошибка сегментации (ядро сброшено)

Matt
источник
13
Называть mainсебя - это на самом деле неопределенное поведение, если вы не знали :) Кроме того, хвостовая рекурсия не гарантированно разрушит ваш стек. Если вам нужна «гарантия», вы должны что- то сделать после рекурсивного вызова, иначе компилятор может оптимизировать рекурсию в бесконечный цикл.
fredoverflow
0

Тот, который еще не был упомянут:

((void(*)())0)();

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

Антон Голов
источник
3
Я знаю несколько машин, что это приведет к перезагрузке, поскольку код запуска ОС фактически сопоставлен с адресом 0. Не думайте, что все будет работать как ваш ПК. Можно сказать, что это был сбой, но он не очень полезен, так как вы не можете отладить его, так как все состояние стирается при запуске.
Мартин Йорк
@Loki Astari: Я, тем не менее, скажу, что это сбой - если это может вызвать его, то и отлаживаемая программа может также быть хорошей, то есть это такой же хороший тест, как и любой другой. С другой стороны, мне любопытно, какая из этих машин может работать с Python.
Антон Голов
Я думаю, что вы упустили момент. Я видел код ОС на 0. Это не значит, что не существует систем с нормальным хорошим кодом для работы, которые будут прекрасно работать на 0. Или байты на 0 могут с такой же легкостью быть кодом операции возврата.
Мартин Йорк,
Я знаю код ОС на 0; это одна из причин, по которой я сильно сомневаюсь, что байты в 0 будут кодом операции возврата. Программа явно больше не выполняется и не выходит обычным способом, то есть она вылетает - если этого недостаточно для спрашивающего, я ожидаю, что он сам прокомментирует это.
Антон Голов
2
Вам известен код ОС только для вашей машины. То, что я пытаюсь сказать, это то, что это может потерпеть неудачу для вас. Но это ничего не значит. Есть много систем там. Я уверен, что у некоторых из них это может сработать (т. Е. Как при не сбое). Полагаться на специфическое поведение машины / ОС - это плохая идея, которая в долгосрочной перспективе вызывает проблемы с обслуживанием. Идея сайта состоит в том, чтобы продвигать хороший код (а не просто код, который работает).
Мартин Йорк,
0
void main()
{

  int *aNumber = (int*) malloc(sizeof(int));
  int j = 10;
  for(int i = 2; i <= j; ++i)
  {
      aNumber = (int*) realloc(aNumber, sizeof(int) * i);
      j += 10;
  }

}

Надеюсь, это потерпит крах. Приветствия.

Senthil
источник
0
int main()
{
    int *p=3;
    int s;
    while(1) {
        s=*p;
        p++;
    }
}
sc_cs
источник
2
Было бы здорово получить некоторые разъяснения :)
olyv
1
указатель p выйдет за пределы адресного пространства программы, что приведет к ошибке памяти, поскольку процесс не может получить доступ к памяти другого процесса. Это приведет к падению программы. указатель p указывает на случайное место в его адресном пространстве, если он в некоторой точке постепенно увеличивается и разыменовывается, он указывает на адресное пространство другой программы (процесса). так что через некоторое время он рухнет.
sc_cs
Или, гипотетически, это может привести к целочисленному переполнению и бесконечному обтеканию. Я бы попытался использовать long longили size_tи начать с pсоответствующего максимального значения, или близко к нему, чтобы сбой быстрее. Хотя даже в этом случае сбой не гарантирован.
Патрик Робертс
0

Стильный способ сделать это - вызов чисто виртуальной функции:

class Base;

void func(Base*);

class Base
{
public:
   virtual void f() = 0;
   Base() 
   {
       func(this);
   }
};

class Derived : Base
{
   virtual void f()
   {
   }
};

void func(Base* p)
{
   p->f();
}


int main()
{
    Derived  d;
}

Скомпилированный с GCC, это печатает:

чисто виртуальный метод называется

завершить вызов без активного исключения

Прервано (ядро сброшено)

Мартин Бродхерст
источник
0

Вы можете использовать ассемблер в своем c ++, code НО INT 3 только для систем x86, в других системах могут быть другие инструкции прерывания / прерывания.

int main()
{
    __asm int 3;

    return 0;
}

INT 3 вызывает прерывание и вызывает вектор прерывания, установленный ОС.

BattleTested
источник
0

Используйте __builtin_trap () в GCC или clang, или __debugbreak () в MSVC. Несоблюдение этих контрольных точек / ловушек приведет к необработанному исключению / аварийному завершению. Другие предложения, которые используют abort () или exit (): они могут обрабатываться другими потоками, что затрудняет просмотр стека потока, который распространялся на сбой.

Дж Хаксли
источник
-2
char*freeThis;
free(freeThis);

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

Z Rev
источник