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

jon*_*opf 309 c++ crash

我正在尝试制作一个与不同的崩溃过程接口的Python程序(这不在我的手中).不幸的是,我正在连接的程序甚至没有可靠的崩溃!所以我想制作一个快速崩溃的C++程序,但我实际上并不知道最好和最短的方法,有谁知道我的:

int main() {
    crashyCodeGoesHere();
}
Run Code Online (Sandbox Code Playgroud)

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

dus*_*uff 255

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

  • @Xeo:如果它确实调用了析构函数和`atexit`s,它现在不会崩溃吗? (137认同)
  • 请注意,通过`abort()`崩溃不会调用任何析构函数或`atexit`函数,尽管这可能无关紧要. (13认同)
  • 不,因为它不会导致崩溃,仅报告无法完成的事情. (9认同)

Mar*_*ork 113

尝试:

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

在发现:

#include <signal.h>
Run Code Online (Sandbox Code Playgroud)

  • 它将以与应用程序中的普通SIGSEGV完全相同的方式崩溃(这是大多数应用程序崩溃的方式).它的定义很明确(默认情况下,它退出应用程序并生成核心文件).是的,你可以设置一个处理程序,但如果你有一个,你不想以同样的方式测试! (12认同)
  • 它不仅仅是实现定义的 - 信号可以用`signal()`捕获.但是,大多数理智的应用程序都没有. (3认同)
  • +1 为`raise()`。这使您只需更改参数即可测试大量不同类型的异常。 (2认同)
  • 最喜欢的解决方案,但它依赖于平台. (2认同)

Roe*_*rel 74

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

int main()
{
    return 1 / 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 根据编译器的聪明程度,这将在编译时捕获.我知道visual studio 2008不会为c ++或c#编译它. (28认同)
  • 为了K&R的缘故,_stop_已经写出了`void main()`! (13认同)
  • 这是未定义的行为,不保证会崩溃。通常编译器假设未定义的行为是不可访问的。这可能导致 `main` 的主体被完全删除,包括 `ret` 指令。执行可能只属于以下功能。 (3认同)
  • 我已经编译并运行了它,你想让我给你打磨 .exe 吗? (2认同)
  • iirc它不会在手臂上崩溃 (2认同)

Kei*_*las 64

*((unsigned int*)0) = 0xDEAD;
Run Code Online (Sandbox Code Playgroud)

  • 这不能保证崩溃. (53认同)
  • "但是哪个理智的操作系统不能阻止试图访问地址0的内存的应用程序?" - 这不是你想问的问题,但无论如何我都会回答.在某些计算机中,地址为0的RAM,对于程序在那里存储值是完全有意义的.一个更有意义的问题是"哪个操作系统不会停止在C++实现为空指针保留的地址访问内存的应用程序?" 在那种情况下,我不知道.但最初的程序是关于C++语言而不是操作系统. (29认同)
  • 虽然这不是*保证*崩溃,但它是C++中最常见的*崩溃之一*.因此,如果你想模拟崩溃,这是一种"真实"的方式来做到这一点:) (28认同)
  • @Windowsprogrammer:不,它不是*保证*.但是哪个理智的OS*不会*停止尝试访问地址0的内存的应用程序? (8认同)
  • 它未定义的行为.这无所事事是完全可以的.一台不会崩溃的机器:运行Z80系列处理器的任何东西(我假设(我的Z80a什么都不做)). (6认同)
  • @KeithNicholas:我原来的观点是成立的.我刚刚想出了一个顶上的系统.假设它会崩溃是一个坏主意,因为可能在你的PC上崩溃并不意味着它比这更进一步.假设PC是主流架构,很多人都受到了伤害.最近发展方面发生了巨大变化,许多开发已经转移到移动设备,因为有些假设不再存在.谁知道下一次架构改变将会发生什么/何时发生.依赖(或习惯)以特定方式工作的未定义行为将导致以后的坏事. (5认同)
  • @JoachimSauer:Mac OS Classic将是一个这样的操作系统(Mac OS X,当然,确实会停止程序). (4认同)
  • @JoachimSauer:HPUX允许读取和写入0.而且这是一个最新的操作系统,仍然有人在运行它. (4认同)
  • @Loki:你在基于Z80的系统上运行python?我印象深刻; 我认为你不能在8位系统上解决足够的内存来做到这一点...... (3认同)
  • @Loki,我想在问题的上下文中,这没关系.这家伙只是想要一个临时的崩溃方法来引导他的python测试代码.这种方法是C++系统常见的*真实*崩溃.除了中止,这是一个非"真正的"崩溃,没有明确的崩溃方式,因为几乎通过定义,当您进入未定义行为的土地时会发生崩溃. (3认同)
  • @Keith Nichola:我不同意.这个问题将被更多的人阅读,而不是OP试图弄清楚如何导致崩溃.我们需要回答这个问题,并考虑这些人. (3认同)
  • 那是UB。它不仅仅依赖于体系结构,编译器可以假设永远不会到达此代码。`echo 'void crash(void) { *(unsigned *)0 = 0xdead; }' | clang -std=c99 -O2 -c -xc -` 给出 `&lt;stdin&gt;:1:20: 警告:非易失性空指针的间接性将被删除,而不是陷阱 [-Wnull-dereference]` 并建议使用任一` __builtin_trap` 或 `*(volatile unsigned *)0`。 (2认同)

sam*_*var 52

那么,我们是否堆栈溢出,或不?

for (long long int i = 0; ++i; (&i)[i] = i);
Run Code Online (Sandbox Code Playgroud)

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

  • 崩溃的算法不是O(1)! (68认同)
  • 我可以看到在具有非受保护代码页的系统上很有趣,并且您使用一些代码来覆盖您的程序,这些代码意外地是一个无效循环.高度极不可能,但可能是可能的. (4认同)

Mac*_*cke 35

 throw 42;
Run Code Online (Sandbox Code Playgroud)

只是答案...... :)


Dan*_*n F 15

assert(false); 也很不错.

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

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

#define assert(ignore) ((void)0)
Run Code Online (Sandbox Code Playgroud)

断言宏根据每次包含的NDEBUG的当前状态重新定义.

[...]

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

  • @Tom`assert`在Release模式下等同于`((void)0)`. (8认同)
  • 我不知道为什么他会做这个测试代码的"发布"版本. (3认同)
  • @SethCarnegie不要看到这个错误 - 只有定义的NDEBUG定义不会崩溃?Dans回答相当公平恕我直言. (2认同)

Pla*_*aHH 11

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

虽然raise(SIGABRT)具有相同的效果,但写作肯定更多.但是,可以通过安装信号处理程序来拦截这两种方式SIGABRT.因此,根据您的情况,您可能需要/需要提出另一个信号.SIGFPE,SIGILL,SIGINT,SIGTERM或者SIGSEGV可能是要走的路,但他们都可以被截获.

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


sam*_*dhi 9

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

它通过异常程序终止来中止进程.它生成SIGABRT信号,默认情况下会导致程序终止将不成功的终止错误代码返回给主机环境.程序终止而不执行自动或静态存储持续时间对象的析构函数,并且不调用任何atexit(在程序终止之前由exit()调用)函数.它永远不会返回其调用者.


Pau*_*gar 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
}
Run Code Online (Sandbox Code Playgroud)

  • 您应该完全放弃它并改用 jQuery。 (2认同)

Abh*_*nav 8

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

我们必须做一个函数,所以让我们离开析构函数等.

ISO/IEC14882§15.1-7的一个例子.根据C++标准应该是崩溃.可以在此处找到Ideone示例.

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) { }
}
Run Code Online (Sandbox Code Playgroud)

ISO/IEC14882§15.1/ 9提到不带try块的throw会导致对abort的隐式调用:

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

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


wrr*_*ren 6

*( ( char* ) NULL ) = 0;
Run Code Online (Sandbox Code Playgroud)

这将产生分段错误.

  • "会发生什么呢?" - 任何事情都可能发生.行为是未定义的,因此实现可以为您的程序的一个变量分配0,或者它可以为您的程序的一个变量分配42,或者它可以格式化您的硬盘并继续执行您的程序. (23认同)
  • 这不能保证崩溃. (10认同)
  • (继续"Windows程序员"的心态)它可以让你的计算机爆炸,或者它可能使它变为现实并接管人类.或者......它将以99.9%的速度崩溃,并且它被定义为"未定义的行为",因为没有人愿意对此负责. (7认同)
  • @ cha0site:标准保证是未定义的行为,因为它取消引用空指针.无论你在Linux上观察到什么行为都是在"未定义行为"的保护下允许的 (2认同)

mvd*_*vds 6

这一个失踪了:

int main = 42;
Run Code Online (Sandbox Code Playgroud)

  • 它甚至链接吗? (3认同)

sll*_*sll 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);
}
Run Code Online (Sandbox Code Playgroud)

请参阅Microsoft KB上的原始示例

  • 那么,在优化级别-O2及以上编译gcc 4.6.0时,它可以很好地优化.它需要-O1或更低的段错误. (8认同)
  • 什么会妨碍一个完全智能编译器优化掉未使用的堆栈分配和尾调用? (4认同)

fre*_*low 5

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

0[""]--;
Run Code Online (Sandbox Code Playgroud)

顺便说一句,g ++拒绝对此进行编译。编译器变得越来越聪明:)