Какой самый простой способ вызвать сбой программы на C ++? - PullRequest
306 голосов
/ 13 декабря 2011

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

int main() {
    crashyCodeGoesHere();
}

для надежного сбоя моей программы на C ++

Ответы [ 28 ]

8 голосов
/ 14 декабря 2011

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

Цитирование из C ++ Стандарт ИСО / МЭК 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) { }
}

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

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:

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

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

6 голосов
/ 17 февраля 2012

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

int main = 42;
5 голосов
/ 14 декабря 2011

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

#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

5 голосов
/ 13 декабря 2011
*( ( char* ) NULL ) = 0;

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

5 голосов
/ 27 сентября 2012

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

0[""]--;

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

4 голосов
/ 13 декабря 2011
int i = 1 / 0;

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

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

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

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

4 голосов
/ 13 декабря 2011

Это более гарантированная версия прерывания, представленная в приведенных выше ответах. Она заботится о ситуации, когда 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();
}
3 голосов
/ 17 декабря 2011
int* p=0;
*p=0;

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

2 голосов
/ 05 января 2017

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

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

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

2 голосов
/ 07 октября 2016

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

  volatile int* a = reinterpret_cast<volatile int*>(NULL);
  *a = 1;
...