【问题标题】:Why does FormatMessage only create partial messages for ERROR_SYSTEM_PROCESS_TERMINATED and ERROR_UNHANDLED_EXCEPTION system errors?为什么 FormatMessage 只为 ERROR_SYSTEM_PROCESS_TERMINATED 和 ERROR_UNHANDLED_EXCEPTION 系统错误创建部分消息?
【发布时间】:2016-10-03 10:54:30
【问题描述】:

我一直在使用 Windows API 中的 FormatMessage 函数从系统错误代码生成消息字符串。我注意到对于某些错误代码,似乎没有创建完整的消息。

以这个示例程序为例:

int main()
{
  wchar_t * buffer = nullptr;
  FormatMessageW(
    FORMAT_MESSAGE_FROM_SYSTEM 
    | FORMAT_MESSAGE_ALLOCATE_BUFFER 
    | FORMAT_MESSAGE_IGNORE_INSERTS, 
    nullptr, 
    ERROR_SYSTEM_PROCESS_TERMINATED,
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    reinterpret_cast<LPWSTR>(&buffer), 
    0, 
    nullptr);

  std::wcout << buffer << std::endl;
  return 0;
}

根据MSDN 我应该看到以下内容:

{致命系统错误}
%hs 系统进程意外终止,状态为 0x%08x (0x%08x 0x%08x)。系统已关闭。

但是,在示例程序中我会看到:

{致命系统错误}
%hs 系统进程意外终止,状态为 0x

我注意到ERROR_UNHANDLED_EXCEPTION 也没有创​​建完整的消息(与 MSDN 上的列表相比)。两条预期消息都包含 0x%08 占位符,但消息在 0x 之后结束。

据我所知,其他错误消息似乎与 MSDN 上的列表匹配(即问题似乎仅限于 ERROR_UNHANDLED_EXCEPTIONERROR_SYSTEM_PROCESS_TERMINATED)。


感谢 engf-010 - 如果您使用 Visual Studio 中的错误查找工具(工具 - 错误查找),您会得到相同的结果。错误代码为 574 和 591。


有谁知道为什么要裁剪这些消息?

有没有办法得到完整的消息?

【问题讨论】:

  • 你应该经常检查系统调用的返回值!它可能会对您的问题有所启发。
  • @engf-010 - 如果我在FormatMessageW 之前将最后一个错误设置为0,则GetLastError()FormatMessageW 之后立即显示为0。
  • 附带说明,您应该LocalFree/HeapFree 使用FORMAT_MESSAGE_ALLOCATE_BUFFER 时返回的缓冲区。尽管这在这个小例子中可能不相关。
  • 不将FORMAT_MESSAGE_IGNORE_INSERTS 用于任意系统错误代码是一个错误(如documented)。请将其包含在您的代码中(而不仅仅是进一步提及)。
  • 有点让人放心:错误查找实用程序给出了相同的错误描述,所以如果 MS 不能正确处理...

标签: c++ winapi visual-c++-2015 formatmessage


【解决方案1】:

您提到的消息(ERROR_UNHANDLED_EXCEPTIONERROR_SYSTEM_PROCESS_TERMINATED)具有 printf 样式插入(%08x)。但是,FormatMessage 使用 %0 来终止消息。

我的猜测是,系统返回这些消息的另一种途径是已经填充了 printf 样式的占位符;这些原始形式的消息不应该由 FormatMessage 处理。

鉴于这些消息包含文本(Fatal System Error)(Application Error),Windows 专门处理这些消息也就不足为奇了。

【讨论】:

  • 我更倾向于相信,FormatMessage 的返回值不应该被冲到下水道……
  • “鉴于这些是致命的系统错误” - 不,它们不是。它们(可能)是致命的过程错误。系统没有什么是非常担心的。内核销毁进程对象,然后继续前进。这种情况一直在发生。
  • @IInspectable 我已更新答案以表明此术语(致命系统错误)来自错误消息的文本。
  • 我不能肯定地说,但问题似乎是 API 中的疏忽/限制。它与检索系统错误消息的推荐方法背道而驰。我能看到的唯一解决方法是在格式化之前检查错误代码,然后分支为我找到的 2 个场景创建预期的消息。
  • @jdigital: ERROR_UNHANDLED_EXCEPTION 可能会出现在未处理的异常过滤器中(请参阅SetUnhandledExceptionFilter),因此它可能会出现在您的进程中。
猜你喜欢
  • 2011-01-10
  • 2015-05-02
  • 1970-01-01
  • 2013-03-18
  • 2022-01-21
  • 1970-01-01
  • 2012-02-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多