故意崩溃的代码[重复]
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( !(<something is wrong>) );
我怀疑原程序员的意图是导致程序在生产环境中运行时“不可恢复地”失败,或者导致调试器中断(如果一个存在)。我不喜欢这种结构,但我看到人们认为这是实现这种效果的唯一“可靠”跨平台方式。我个人不会使用它。
这太可怕了。如果您知道程序出错但不确定原因,您应该转储您认为有助于解决问题的所有内容。在没有任何线索的情况下使程序崩溃是牛仔编程恕我直言......
C++ 中不存在“空引用异常”。
【参考方案1】:
您不能故意“使程序崩溃”,因为根据其定义,崩溃是指程序出现错误并且无法确定性地运行。
终止执行的标准方法是通过std::terminate
;实现这一点的常用方法是调用std::abort
,这会针对进程发出不可阻塞的信号(自动导致std::terminate
)并且还会导致许多操作系统产生核心转储。
【讨论】:
不是反过来吗?std::terminate
调用std::abort
,这又会引发一个信号,等等。
@DaniloPiazzalunga:不,我不这么认为。但是,我在标准中发现了一些额外的信息:通常未指定未捕获的信号是否会导致堆栈展开,但调用 std::abort
确实 not 会导致任何展开。 (即,这正是 OP 需要的东西。)
我们实际上不在这里使用 C++ STL(或 Boost 或任何其他外部库) - 我们有自己的内部 STL,所以您不会在此看到 std::anything
代码库。甚至对于字符串也不行。我不知道它是否有可用的abort
或terminate
...【参考方案2】:
您应该抛出一个异常,这基本上是故意以可控的方式导致崩溃。这是一个来自this question 帮助的示例。
throw string("something_went_wrong");
更好的是错误被捕获或修复。 Assert 也是一个不错的选择。
【讨论】:
我最近编程的java太多了...无论如何,将示例更改为更好的东西。 不,例外是完全不同的事情。异常的目的是触发一个不常见的错误,应用程序可以从中恢复,在这种情况下,目的是在应用程序无法恢复时杀死应用程序。 未捕获的异常会表现得与当前行为相似,另外还有一个好处是更容易发现,可以提供更有意义的堆栈跟踪,并且可以在以后通过捕获错误来修复. 我特别赞成这一点,因为 OP 提到了他的代码“......不会抛出异常,所以它不能被其他代码处理。”【参考方案3】:我想这是在您不调试的情况下触发核心转储的方法。然后核心转储会为您提供足够的信息来分析问题。在“程序员错误”(或错误)的情况下,这比抛出异常要好,因为堆栈展开不允许您构建合理的核心转储。可以通过调用 std::terminate 以更优雅的方式实现类似的效果,该 std::terminate 先前已注册(使用 std::set_terminate)生成核心转储或类似内容的函数。更详细的解释见this article。
【讨论】:
以上是关于故意崩溃的代码[重复]的主要内容,如果未能解决你的问题,请参考以下文章