崩溃的程序和挂起的程序之间的区别

时间:2009-12-16 03:18:56

标签: c++

崩溃的程序与在C ++中挂起(变得无法响应)的程序之间有什么区别(或原因)?

当然,访问无效内存会导致程序崩溃。线程中的死锁可能导致程序挂起。还有什么其他原因?

耗尽所有内存会导致程序挂起吗?或者崩溃?我在差异和原因之间有点困惑。

6 个答案:

答案 0 :(得分:12)

崩溃通常是由非法指令引起的,例如访问无效内存,除以零等。通常这表现为一个众所周知的异常,由操作系统处理。

可分为两个相当高级别的类别:

  • 死锁,通常由2个竞争资源的线程引起,每个线程都需要释放另一个线程所持有的资源。造成这种情况的一个常见原因是在多个线程内以不一致的顺序获取多个锁,从而产生共同的ABBA deadlock pattern(并且这与瑞典流行音乐没有任何关系)。
  • Livelock ,这意味着代码仍在运行,但您已达到无法离开的状态。例如:
    • 2个进程/线程的状态不断变化,永远不会达到最终状态
    • while循环,其中永远不会满足退出条件,或无限循环(虽然这会拉伸“活锁”的定义)。

根据问题评论进行更新

  @Pop,Kristo:我实际上正在检查   一个挂起的代码,但我看到了一些   内存泄漏问题。但我不是   确定内存泄漏是否会导致问题   程序挂起。 - jasonline

内存泄漏可能导致程序崩溃,但这取决于各种因素:

  • 泄漏大小
  • 泄漏频率
  • 申请寿命

内存泄漏可能导致2件坏事 - 进程内存使用量不断增加,以及内存碎片化。如果操作系统无法提供连续的内存块,则这两种情况都可能导致无法在线路上分配内存。

在C ++中,如果new运算符无法分配内存,则会抛出std::bad_alloc异常。这很可能会被操作系统捕获,从而导致崩溃(除非您在应用程序中为此异常编写了特定的处理程序,并且能够更优雅地处理它)。

答案 1 :(得分:0)

等待外部资源(主要是网络)也可能导致挂起。虽然这通常会在一段时间后超时。挂起也可能是由处理与处理相关的事情的线程终止引起的。例如,如果UI线程调度了一个工作线程来完成某些工作并且工作线程已经死亡,那么该程序似乎会挂起。

答案 2 :(得分:0)

很多时候Windows应用程序都会挂起,因为他们的消息循环处理会发生一些事情。由于所有程序事件一旦被泄露就会通过消息循环,程序就会无法响应。

您可以在此处详细了解消息循环的工作原理:

http://www.winprog.org/tutorial/message_loop.html

答案 3 :(得分:0)

挂起和崩溃之间的一个重要因素是与软件和硬件异常处理和/或保护机制提供的支持相关的底层操作系统。例如,在旧的DOS世界中,当在实模式下操作时,您可能会挂起整个系统并使用无效的内存访问(因为386> DOS扩展程序因异常而崩溃,至少是DOS4GW之类的流行程序)。

除了死锁之外,操作系统和运行时库的适当支持可以阻止用户模式应用程序的大多数异常和错误行为。

在内核模式代码中,悬挂的可能性当然要高得多。

答案 4 :(得分:0)

看起来你已经回答了自己的问题。

我可以想到崩溃的其他几个原因:

  • 非法指示。例如,如果您在旧CPU上运行SSE代码。
  • 内存访问不当非常模糊。存在这样的子情况,例如某些CPU上的单词的未对齐访问,堆栈溢出,对未映射页面的访问,写入只读页面,执行非可执行页面,导致破坏不变量的并发访问,以及名称一些......
  • 在Linux上,如果系统内存非常低,您的进程可能会被杀死(看似随机)。 (请参阅此搜索"OOM killer"

除了死锁,你还有:

  • "Livelocks".
  • UI线程被某些其他操作阻止(某些示例:I / O,在内存不足的情况下将页面逐出磁盘)
  • 其他程序员错误,例如在某些未经测试的情况下永远不会终止的循环。

答案 5 :(得分:0)

从您的评论中,您的内存泄漏可能与相关到您的挂起,而不是原因。也就是说,你可能有一些像无限循环那样简单的东西,它可以在每次迭代中获得更多的内存。