Почему FormatMessage создает только частичные сообщения для системных ошибок ERROR_SYSTEM_PROCESS_TERMINATED и ERROR_UNHANDLED_EXCEPTION?

Я использовал функцию FormatMessage в Windows API для создания строк сообщений из кодов системных ошибок. Я заметил, что для некоторых кодов ошибок полное сообщение не создается.

В качестве примера возьмем эту примерную программу:

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 I должен увидеть следующее:

{Неустранимая системная ошибка}
Системный процесс% hs неожиданно завершился со статусом 0x% 08x (0x% 08x 0x% 08x). Система была закрыта.

Однако в программе-примере я увижу:

{Fatal System Error}
Системный процесс% hs неожиданно завершен со статусом 0x

Я заметил, что ERROR_UNHANDLED_EXCEPTION также не создает полное сообщение (по сравнению со списком в MSDN). Оба ожидаемых сообщения содержат заполнители 0x% 08, но сообщение заканчивается после 0x.

Насколько я могу судить, другие сообщения об ошибках соответствуют спискам в MSDN (т.е. проблема ограничена ERROR_UNHANDLED_EXCEPTION и ERROR_SYSTEM_PROCESS_TERMINATED).


Кредит engf-010 - вы получите то же самое, если используете инструмент поиска ошибок в Visual Studio (Инструменты - Поиск ошибок). Коды ошибок - 574 и 591.


Кто-нибудь знает, почему эти сообщения обрезаются?

Есть ли способ получить полное сообщение?


person Class Skeleton    schedule 03.06.2016    source источник
comment
Вы всегда должны проверять возвращаемое значение системных вызовов! Это может пролить свет на вашу проблему.   -  person engf-010    schedule 03.06.2016
comment
@ engf-010 - Если я установил последнюю ошибку как 0 перед FormatMessageW, GetLastError() сразу после FormatMessageW будет отображаться как 0.   -  person Class Skeleton    schedule 03.06.2016
comment
В качестве примечания, вы должны _1 _ / _ 2_ буфер, возвращаемый при использовании FORMAT_MESSAGE_ALLOCATE_BUFFER. Хотя это может не иметь отношения к этому небольшому примеру.   -  person Christian.K    schedule 03.06.2016
comment
Отсутствие использования FORMAT_MESSAGE_IGNORE_INSERTS для произвольных кодов системных ошибок является ошибкой (как описано в ). Пожалуйста, включите это в свой код (а не просто упомяните об этом ниже).   -  person IInspectable    schedule 03.06.2016
comment
@ Christian.K - да, это в производственном коде.   -  person Class Skeleton    schedule 03.06.2016
comment
Несколько обнадеживает: утилита поиска ошибок дает то же описание ошибки, поэтому, если MS не может сделать это правильно ...   -  person engf-010    schedule 03.06.2016
comment
Было ли это когда-нибудь решено?   -  person mrexodia    schedule 29.10.2017


Ответы (1)


В упомянутых вами сообщениях (ERROR_UNHANDLED_EXCEPTION и ERROR_SYSTEM_PROCESS_TERMINATED) есть вставки в стиле printf (%08x). Однако FormatMessage использует% 0 для завершения сообщения.

Я предполагаю, что есть еще один способ, по которому эти сообщения возвращаются системой с уже заполненными заполнителями в стиле printf; эти сообщения в их необработанном виде не предназначены для обработки FormatMessage.

Учитывая, что эти сообщения содержат текст (Fatal System Error) или (Application Error), неудивительно, что Windows обрабатывает эти сообщения особым образом.

person jdigital    schedule 03.06.2016
comment
Я более склонен полагать, что возвращаемое значение FormatMessage не следует смывать в канализацию ... - person IInspectable; 03.06.2016
comment
Учитывая, что это фатальные системные ошибки - нет, это не так. Это (потенциально) фатальные ошибки процесса. Ничего страшного для системы. Ядро уничтожает объекты процесса и продолжает работу. Это происходит все время. - person IInspectable; 03.06.2016
comment
@IInspectable Я обновил ответ, чтобы указать, что эта терминология (Неустранимая системная ошибка) исходит из текста сообщения об ошибке. - person jdigital; 03.06.2016
comment
Я не могу сказать наверняка, но похоже, что проблема в недосмотре / ограничении в API. Это противоречит рекомендуемому подходу к получению сообщений об ошибках системы. Единственный обходной путь, который я вижу, - это проверить код ошибки перед форматированием, а затем разветвляться, чтобы создать ожидаемые сообщения для двух найденных мной сценариев. - person Class Skeleton; 03.06.2016
comment
Если мне понятны эти коды ошибок, вы не увидите их в своем приложении. - person jdigital; 03.06.2016
comment
@jdigital: ERROR_UNHANDLED_EXCEPTION скорее всего будет отображаться в фильтре необработанных исключений (см. SetUnhandledExceptionFilter), поэтому это может произойти в вашем процессе. - person IInspectable; 03.06.2016
comment
@IInspectable: не могли бы вы рассказать об этом подробнее? Я не понимаю, как это могло бы случиться. - person Harry Johnston; 04.06.2016