故意崩溃的代码[重复]

Posted

技术标签:

【中文标题】故意崩溃的代码[重复]【英文标题】:Code to crash intentionally [duplicate] 【发布时间】:2012-11-10 05:38:33 【问题描述】:

可能重复:What is the easiest way to make a C++ program crash?

我经常在我们的代码库中看到一种结构,即程序以某种方式进入无效状态,代码会故意做错事,只是为了强制崩溃。它通常是这样的:

if(<something is wrong>)

    int *ptr = NULL;
    *ptr = 0;

这当然会导致空引用异常并以不可恢复的方式使程序崩溃。我只是想知道这是否真的是最好的方法?首先,它读起来不好。如果没有评论,您可能不会意识到这里发生的崩溃是故意的。其次,几乎没有办法从中恢复。它不会抛出异常,因此无法由其他代码处理。它只是杀死程序而无法回溯。它也没有提供太多关于为什么它必须在这里崩溃的线索。它会在所有构建中崩溃,不像断言。 (我们确实有一个非常强大的断言系统可用,但它并不总是在这种情况下使用。)

这是我们到处都在使用的风格,否则我无法说服任何人。我只是好奇这在行业中有多普遍。

【问题讨论】:

为什么不直接使用abort() assert( !(&lt;something is wrong&gt;) ); 怀疑程序员的意图是导致程序在生产环境中运行时“不可恢复地”失败,或者导致调试器中断(如果一个存在)。我不喜欢这种结构,但我看到人们认为这是实现这种效果的唯一“可靠”跨平台方式。我个人不会使用它。 这太可怕了。如果您知道程序出错但不确定原因,您应该转储您认为有助于解决问题的所有内容。在没有任何线索的情况下使程序崩溃是牛仔编程恕我直言...... C++ 中不存在“空引用异常”。 【参考方案1】:

您不能故意“使程序崩溃”,因为根据其定义,崩溃是指程序出现错误并且无法确定性地运行。

终止执行的标准方法是通过std::terminate;实现这一点的常用方法是调用std::abort,这会针对进程发出不可阻塞的信号(自动导致std::terminate)并且还会导致许多操作系统产生核心转储。

【讨论】:

不是反过来吗? std::terminate 调用std::abort,这又会引发一个信号,等等。 @DaniloPiazzalunga:不,我不这么认为。但是,我在标准中发现了一些额外的信息:通常未指定未捕获的信号是否会导致堆栈展开,但调用 std::abort 确实 not 会导致任何展开。 (即,这正是 OP 需要的东西。) 我们实际上不在这里使用 C++ STL(或 Boost 或任何其他外部库) - 我们有自己的内部 STL,所以您不会在此看到 std::anything代码库。甚至对于字符串也不行。我不知道它是否有可用的abortterminate...【参考方案2】:

您应该抛出一个异常,这基本上是故意以可控的方式导致崩溃。这是一个来自this question 帮助的示例。

throw string("something_went_wrong");

更好的是错误被捕获或修复。 Assert 也是一个不错的选择。

【讨论】:

我最近编程的java太多了...无论如何,将示例更改为更好的东西。 不,例外是完全不同的事情。异常的目的是触发一个不常见的错误,应用程序可以从中恢复,在这种情况下,目的是在应用程序无法恢复时杀死应用程序。 未捕获的异常会表现得与当前行为相似,另外还有一个好处是更容易发现,可以提供更有意义的堆栈跟踪,并且可以在以后通过捕获错误来修复. 我特别赞成这一点,因为 OP 提到了他的代码“......不会抛出异常,所以它不能被其他代码处理。”【参考方案3】:

我想这是在您不调试的情况下触发核心转储的方法。然后核心转储会为您提供足够的信息来分析问题。在“程序员错误”(或错误)的情况下,这比抛出异常要好,因为堆栈展开不允许您构建合理的核心转储。可以通过调用 std::terminate 以更优雅的方式实现类似的效果,该 std::terminate 先前已注册(使用 std::set_terminate)生成核心转储或类似内容的函数。更详细的解释见this article。

【讨论】:

以上是关于故意崩溃的代码[重复]的主要内容,如果未能解决你的问题,请参考以下文章

故意使我的 Windows 应用程序崩溃的最佳方法是啥?

按钮代码崩溃应用[重复]

在源代码管理中,每个项目拥有一个大存储库还是一个存储库更好? [复制]

Linux 上的 .NET 崩溃了怎么抓 Dump

Firebase Crashlytics 未报告崩溃

Java 你还在用lsit.contain做去重? 你是故意的还是不小心的?