使C ++程序崩溃的最简单方法是什么?

时间:2011-12-12 22:26:23

标签: c++ crash

我正在尝试创建一个与不同崩溃进程(这不在我手中)的Python程序。不幸的是,我正在连接的程序甚至没有可靠的崩溃!所以我想制作一个快速崩溃的C ++程序,但我实际上并不知道这样做的最佳和最短的方法,有谁知道在我之间放什么:

int main() {
    crashyCodeGoesHere();
}

使我的C ++程序可靠地崩溃

30 个答案:

答案 0 :(得分:248)

abort()功能可能是您最好的选择。它是C标准库的一部分,定义为“导致程序异常终止”(例如,致命错误或崩溃)。

答案 1 :(得分:107)

尝试:

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

发现于:

#include <signal.h>

答案 2 :(得分:74)

除以零会使应用程序崩溃:

int main()
{
    return 1 / 0;
}

答案 3 :(得分:64)

*((unsigned int*)0) = 0xDEAD;

答案 4 :(得分:50)

嗯,我们是否堆叠 溢出,或不是?

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

(不保证可以通过任何标准崩溃,但也不是任何建议的答案,包括已接受的答案,因为SIGABRT可能已被捕获。实际上,这将在任何地方崩溃。)

答案 5 :(得分:34)

 throw 42;

答案是......:)

答案 6 :(得分:15)

assert(false);也很不错。

根据ISO / IEC 9899:1999,保证在未定义NDEBUG时崩溃:

  

如果定义了NDEBUG,则断言宏被简单地定义为

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

每次包含时,都会根据NDEBUG的当前状态重新定义断言宏。

     

[...]

     

断言宏将诊断测试放入程序中; [...]如果表达式(具有标量类型)是假的[...]。它   然后调用中止函数。

答案 7 :(得分:11)

由于崩溃是调用未定义行为的一种症状,并且由于调用未定义的行为可能导致任何事情,包括崩溃,我认为您不想真正崩溃您的程序,而只是将其放入调试器中。最便携的方式可能是abort()

虽然raise(SIGABRT)具有相同的效果,但写作肯定更多。但是,可以通过为SIGABRT安装信号处理程序来拦截这两种方式。因此,根据您的情况,您可能需要/需要提出另一个信号。 SIGFPESIGILLSIGINTSIGTERMSIGSEGV可能是最佳选择,但它们都可以被截获。

当您无法移植时,您的选择可能会更广泛,例如在Linux上使用SIGBUS

答案 8 :(得分: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
}

答案 9 :(得分:9)

我唯一的闪光是 abort()函数

它在程序终止异常时中止进程。它生成 SIGABRT信号,默认情况下会导致程序终止向主机环境返回不成功的终止错误代码。程序终止< strong>不执行析构函数用于自动或静态存储持续时间的对象,不调用任何 atexit (在程序终止之前由exit()调用)功能。它永远不会回到它的来电者身上。

答案 10 :(得分:7)

C ++可以通过在处理另一个异常时抛出异常来确定性地崩溃!标准说永远不会从析构函数中抛出任何异常,或者从不在析构函数中使用任何可能抛出异常的函数。

我们必须创建一个函数,所以让我们离开析构函数等等。

来自 ISO / IEC14882§15.1-7 的示例。根据C ++标准应该是崩溃。 Ideone example can be found here

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;
}

ISO / IEC14882§15.1/ 9 提及不使用try块而导致隐式调用中止:

  

如果目前没有处理异常,则执行a   没有操作数的throw-expression调用std :: terminate()

其他包括: 从析构函数抛出: ISO / IEC14882§15.2/ 3

答案 11 :(得分: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);
}

请参阅Original example on Microsoft KB

答案 12 :(得分:5)

*( ( char* ) NULL ) = 0;

这会产生分段错误。

答案 13 :(得分:5)

缺少这个:

int main = 42;

答案 14 :(得分:4)

int i = 1 / 0;

你的编译器可能会警告你这个,但它在GCC 4.4.3下编译得很好 这将可能导致SIGFPE(浮点异常),这可能不像其他答案那样在实际应用中像SIGSEGV(内存分段违规)那样,但它仍然是崩溃。在我看来,这更具可读性。

另一种方式,如果我们要作弊并使用signal.h,则是:

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

这可以保证杀死子进程,与SIGSEGV形成对比。

答案 15 :(得分: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();
}

答案 16 :(得分:4)

这在我的Linux系统上崩溃了,因为字符串文字存储在只读内存中:

0[""]--;

顺便说一句,g ++拒绝编译它。编译器变得更聪明,更聪明:)

答案 17 :(得分:3)

int* p=0;
*p=0;

这也应该崩溃。在Windows上它与AccessViolation崩溃,它应该在所有操作系统上做同样的事情。我想。

答案 18 :(得分:2)

写入只读内存会导致分段错误,除非您的系统不支持只读内存块。

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

我在Windows 7上使用MingGW 5.3.0和在Linux Mint上使用GCC进行了测试。我想其他编译器和系统会产生类似的效果。

答案 19 :(得分:2)

这是Google在Breakpad中提供的代码段。

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

答案 20 :(得分:2)

int main(int argc, char *argv[])
{
    char *buf=NULL;buf[0]=0;
    return 0;
}

答案 21 :(得分:2)

虽然这个问题已经得到了接受的答案......

void main(){
    throw 1;
}

或...... void main(){throw 1;}

答案 22 :(得分:1)

或者另一种方式,因为我们在乐队旅行车上。

一段可爱的无限递归。保证可以吹你的筹码。

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

打印出来:

  

分段错误(核心转储)

答案 23 :(得分:0)

int main()
{
    int *p=3;
    int s;
    while(1) {
        s=*p;
        p++;
    }
}

答案 24 :(得分: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编译,打印:

  

名为

的纯虚方法      

在没有活动异常的情况下终止被调用

     

中止(核心倾销)

答案 25 :(得分: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;
  }

}

希望这会崩溃。欢呼声。

答案 26 :(得分:0)

尚未提及的一个:

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

这会将空指针视为函数指针,然后调用它。就像大多数方法一样,这并不能保证程序崩溃,但操作系统允许不加以检查以及程序返回的可能性可以忽略不计。

答案 27 :(得分:0)

您可以在c ++ code中使用汇编语言 BUT INT 3仅用于x86系统,其他系统可能具有其他陷阱/断点指令

int main()
{
    __asm int 3;

    return 0;
}

INT 3引起中断并调用由操作系统设置的中断向量。

答案 28 :(得分:0)

在GCC或clang中使用__builtin_trap(),在MSVC中使用__debugbreak()。不处理这些断点/陷阱将导致未处理的断点异常/崩溃。 其他使用abort()或exit()的建议:这些建议可能由其他线程处理,这使得查看导致崩溃的线程堆栈更加困难。

答案 29 :(得分:-2)

char*freeThis;
free(freeThis);

释放未初始化的指针是未定义的行为。在许多平台/编译器上,freeThis将具有随机值(之前在该内存位置的任何内容)。释放它将要求系统释放该地址的内存,这通常会导致分段错误并使程序崩溃。