让c++程序崩溃最简单的方法是什么?

我试图使一个Python程序接口与不同的崩溃进程(这是我的手)。不幸的是,我正在使用的程序甚至不会可靠地崩溃!所以我想做一个快速的c++程序,它会故意崩溃,但我不知道最好和最短的方法来做到这一点,有人知道在我的

int main() {
crashyCodeGoesHere();
}

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

97262 次浏览

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

assert(false);也很好。

根据ISO/IEC 9899:1999,当没有定义NDEBUG时,保证会崩溃:

如果NDEBUG定义为[…]assert宏被简单地定义为

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

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

[…]

断言宏将诊断测试放入程序;[…if表达式(它应该有一个标量类型)为假[…]。它 然后调用abort函数

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

这将产生一个分割错误。

试一试:

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

中发现:

#include <signal.h>

由于崩溃是调用未定义行为的症状,并且由于调用未定义行为可能导致任何事情,包括崩溃,我认为您不希望真正使程序崩溃,而只是将它放入调试器中。最可移植的方法可能是abort()

虽然raise(SIGABRT)具有相同的效果,但它肯定更易于编写。然而,这两种方式都可以通过为SIGABRT安装信号处理程序来拦截。因此,根据您的情况,您可能想要/需要发出另一个信号。SIGFPESIGILLSIGINTSIGTERMSIGSEGV可能是可行的方法,但它们都可以被拦截。

当你不能移植时,你的选择可能会更广泛,比如在linux上使用SIGBUS

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

另一种方法,如果我们要欺骗并使用signal.h,是:

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

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

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

它以异常的程序终止终止进程。它生成SIGABRT信号,默认情况下,它会导致程序终止,并向主机环境返回一个不成功的终止错误代码。对于自动或静态存储持续时间的对象,程序被终止不执行析构函数,以及没有调用任何atexit(在程序终止前由exit()调用)函数。它从不返回调用者。

好吧,我们是不是在堆栈溢出 ?

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

(以任何标准都不保证会崩溃,但也没有任何建议的答案,包括被接受的答案,因为SIGABRT无论如何都可能被捕获。实际上,这会在任何地方崩溃。)

这是上面回答中给出的一个更有保证的abort版本。它负责处理sigabrt被阻塞时的情况。实际上,您可以使用任何信号来代替具有使程序崩溃的默认操作的abort。

#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();
}

答案是平台特定的,取决于你的目标。但这里是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
}

死循环递归方法调用导致堆栈溢出怎么办?

#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上的原始示例

我看到这里张贴了许多答案,它们将成为完成工作的幸运案例,但没有一个是100%确定会崩溃的。一些会在一个硬件和操作系统上崩溃,另一些不会。 然而,根据官方c++标准,有一种标准方法可以使它崩溃。< / p >

引用自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;
}

ISO/IEC 14882§15.1/9提到throw没有try块导致隐式调用abort:

如果当前没有异常正在处理,执行a 没有操作数的抛出表达式调用std::terminate()

其他包括: throw from析构函数:ISO/IEC 14882§15.2/3

除以0会导致应用程序崩溃:

int main()
{
return 1 / 0;
}
 throw 42;

只要回答……:)

int* p=0;
*p=0;

这也应该崩溃。在Windows上,它与AccessViolation一起崩溃,我猜它应该在所有操作系统上都是一样的。

这个缺失了:

int main = 42;

或者另一种方式,因为我们都是乐队的。

一个可爱的无限递归。保证会让你大吃一惊。

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

打印出:

分段错误(核心转储)

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

0[""]--;

顺便说一下,g++拒绝编译这个。编译器变得越来越聪明:)

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


}

希望它崩溃。欢呼。

int main(int argc, char *argv[])
{
char *buf=NULL;buf[0]=0;
return 0;
}
int main()
{
int *p=3;
int s;
while(1) {
s=*p;
p++;
}
}

虽然这个问题已经有了公认的答案……

void main(){
throw 1;
}

还是……void main(){throw 1;}

char*freeThis;
free(freeThis);

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

一种时髦的方法是使用纯虚函数调用:

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编译,输出:

纯虚方法调用

在没有活动异常时调用Terminate

中止(核心转储)

这是Breakpad中谷歌提供的代码片段。

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

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

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

我在Windows 7上用MingGW 5.3.0测试了它,在Linux Mint上用GCC测试了它。我认为其他编译器和系统也会有类似的效果。

你可以在c++中使用汇编code < em >, < / em > INT 3仅适用于x86系统,其他系统可能有其他陷阱/断点指令。

int main()
{
__asm int 3;


return 0;
}

INT 3导致中断并调用由OS设置的中断向量。

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

#include <thread>


void intentionalCrash()
{
auto noop = [](){return;};
// Thread t1 is in a joinable state.
// When program returns t1 will be out of scope.
// Destructing a joinable thread creates a crash.
std::thread t1(noop);
}


int main()
{
intentionalCrash();
return 0;
}

简单的缓冲区溢出代码,将导致程序崩溃

int main()
{
int n[0];
n[2] = 0;
}