我正在尝试创建一个与不同崩溃进程(这不在我手中)的Python程序。不幸的是,我正在连接的程序甚至没有可靠的崩溃!所以我想制作一个快速崩溃的C ++程序,但我实际上并不知道这样做的最佳和最短的方法,有谁知道在我之间放什么:
int main() {
crashyCodeGoesHere();
}
使我的C ++程序可靠地崩溃
答案 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
安装信号处理程序来拦截这两种方式。因此,根据您的情况,您可能需要/需要提出另一个信号。 SIGFPE
,SIGILL
,SIGINT
,SIGTERM
或SIGSEGV
可能是最佳选择,但它们都可以被截获。
当您无法移植时,您的选择可能会更广泛,例如在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);
}
答案 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
将具有随机值(之前在该内存位置的任何内容)。释放它将要求系统释放该地址的内存,这通常会导致分段错误并使程序崩溃。