“这个应用程序已请求运行时以异常方式终止”的原因是什么?

62

在 Visual C 运行时中,有一个常见的错误会被抛出:

此应用程序已请求 Runtime 以不正常的方式终止。
请联系应用程序支持团队了解更多信息。

这个错误消息到底是什么意思呢?


让我用一个寓言来解释我的问题。

如果我看到一条消息:

异常:访问冲突 (0xc0000005),地址 0x702be865

这个“访问冲突”与性骚扰或某人试图侵入我的计算机没有任何关系(就像“General Failure”不是一个少将,他试图读取我的C盘一样,或者你被拘留在 Windows 95 中执行非法操作)。

在这种情况下,“访问冲突”对应于常量EXCEPTION_ACCESS_VIOLATION(在winbase.h中声明,并具有值0xC0000005)。这个常量是可以在EXCEPTION_RECORD结构中返回的一种可能的异常错误代码。代码ACCESS_VIOLATION的意思是程序试图读取或写入它不应该访问的内存地址。如果你尝试从未分配的内存地址读取数据,那么你正在做一些非常糟糕的事情——异常信息就是这样告诉你的。

通常情况下,这种错误是由程序拥有指向无效的内存地址的指针引起的。解决方法是停止尝试访问无效的内存地址。

注意:我不是在问以下问题:

  • 为什么程序x会收到C0000005错误?
  • 我的代码为什么会出现访问冲突?
  • 如何调试访问冲突?

所以,如果我问你:是什么导致了访问冲突?,你不会告诉我去检查堆栈跟踪、观察输出窗口或发布示例代码。你会说:"是因为试图访问无效的内存地址。"

回到我的问题

以下错误消息是什么意思:

此应用程序已请求 Runtime 以不正常的方式终止。

我(相当)确定 Microsoft Visual C 运行时库没有一个这样的函数:

void TerminateRuntime(bool UnusualWay);

所以我必须尝试弄清楚它实际上意味着什么:

  • 什么是终止Visual C运行库的意思?(msvcrt是一个dll;你不会终止它,你只是不再使用它)
  • 通常的终止MSVCRT的方法是什么?
  • 会有人选择用不寻常的方式来终止它吗?
  • 今天的不寻常的方式是否实际上是很久以前曾经是通常方式的已过时形式?
  • 如果我错误地用一种不寻常的方式终止它,我该如何用通常的方式来终止它?

换句话说:MSVCRT捕获了什么错误,并将其隐藏在不具信息性的错误消息后面?


当消息说“终止它”时,它意味着终止应用程序,而不是终止运行时。我在MSDN上找不到任何文档,但这个消息在许多论坛主题中被提到:共识似乎是指抛出了异常并且未被捕获。 - Harry Johnston
5
这个问题的撰写非常棒,即使我不需要它也会点赞和加星。特别是,我喜欢你提出的“TerminateRuntime”声明。 (我稍微修改了一些小细节,如大写字母;我印象深刻的是,在我的修改之前,这篇文章已经非常完整和清晰,没有任何(非忍者)编辑。) - Kyle Strand
1个回答

46

当调用abort()函数时,您会收到该消息。

来自 MSDN:

abort

Aborts the current process and returns an error code.

void abort( void );

Return Value

abort does not return control to the calling process. By default, it terminates the current process and returns an exit code of 3.

Remarks

By default, the abort routine prints the message:

"This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information."

似乎在最近的VC运行时版本中,消息已被替换为“abort()已被调用”,可能是为了澄清其真正含义。如果要重现该消息,请使用旧版VC运行时(VC ++ 6.0肯定),并调用 abort()。
在内部,当 abort()被调用时,它会调用一个函数_amsg_exit,该函数定义在internal.h中,基本上“对于控制台应用程序向stderr发出运行时错误消息,或者对于Windows应用程序在消息框中显示消息”。 “此应用程序已请求Runtime以不寻常的方式终止”的错误消息在cmsgs.h中定义:

cmsgs.h:

#define _RT_ABORT_TXT  "" EOL "This application has requested the Runtime to terminate it in an unusual way.\nPlease contact the application's support team for more information." EOL

错误代码(_RT_ABORT)在 rterr.h 中定义:

rterr.h

#define _RT_ABORT  10  /* Abnormal program termination */

因此,您可以通过调用_amsg_exit( _RT_ABORT )来重新生成此问题。


问题提问者更新: 两周后,Raymond Chen在他自己的博客中回答了这个问题:

你运行程序,然后它突然退出,并显示消息"This application has requested the Runtime to terminate it in an unusual way."发生了什么?

该消息是由C运行时函数abort打印, 这个函数也会导致你的程序以退出码3终止

你的程序可能会显式调用abort,或者可能会被运行时库自身隐式调用。

C++标准详细说明了调用terminate的条件,这是一个相当长的列表,我不会在这里重复。请查阅您最喜欢的C++标准副本以获取详细信息。(最常见的原因是抛出未处理的异常。)


3
你赢了。这正是消息的原因,程序员调用了“abort()”函数。如果我想要停止这个错误,开发人员必须停止调用“abort()”。 - Ian Boyd
2
好的回答。我想知道如何解决这种错误?具体来说,如何知道哪个异常未被捕获以及在哪里抛出? - smwikipedia
如果有人像我一样遇到这个问题(我是应用支持团队,无法联系自己),想要找出是谁中止了进程,请参考以下链接的另一个问题,了解如何创建一个可以设置断点的终止函数:https://dev59.com/-3E95IYBdhLWcg3wHqWl - Dtor
1
有没有办法防止消息框被显示出来?在许多情况下,记录错误并直接终止(无需任何用户交互)以便重新启动流程会更好。 - Nils Lande
2
找到了。 _set_abort_behavior(0, _WRITE_ABORT_MSG); 可以用来摆脱微软所谓的“有用信息”。 - Nils Lande

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接