Как получить название / описание исключения? - PullRequest
8 голосов
/ 26 ноября 2008

Как вы получаете имя и / или описание SEH исключения без необходимости жесткого кодирования строк в вашем приложении?

Я пытался использовать FormatMessage(), но иногда оно обрезает сообщение, даже если вы указываете игнорировать вставки:

__asm { // raise access violation
    xor    eax, eax
    mov    eax, [eax]
}

Вызывает исключение с кодом 0xC0000005 (EXCEPTION_ACCESS_VIOLATION).

char msg[256];
FormatMessageA(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS,
    GetModuleHandleA("ntdll.dll"), 0xC0000005,
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    msg, sizeof(msg), NULL);

Заполняет msg усеченной строкой: "The instruction at 0x".

Ответы [ 2 ]

2 голосов
/ 09 октября 2015

Структурированные коды исключений определяются через номера NTSTATUS. Хотя кто-то из MS предлагает , используя FormatMessage () для преобразования чисел NTSTATUS в строки, я бы не стал этого делать. Флаг FORMAT_MESSAGE_FROM_SYSTEM используется для преобразования результата GetLastError () в строку, поэтому здесь нет смысла. Использование флага FORMAT_MESSAGE_FROM_HMODULE вместе с ntdll.dll приведет к неверным результатам для некоторых кодов. Например, за EXCEPTION_ACCESS_VIOLATION вы получите The instruction at 0x, что не очень информативно :).

Когда вы смотрите на строки, хранящиеся в ntdll.dll, становится очевидным, что многие из них должны использоваться с функцией printf () , а не с FormatMessage () . Например, строка для EXCEPTION_ACCESS_VIOLATION:

The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s.

%0 обрабатывается FormatMessage () как escape-последовательность, означающая терминатор сообщения, а не вставка. Вставки от% 1 до% 99. Вот почему флаг FORMAT_MESSAGE_IGNORE_INSERTS не имеет значения.

Возможно, вы захотите загрузить строку из ntdll.dll и передать ее в vprintf, но вам нужно будет подготовить аргументы в точности так, как указано в строке (например, для EXCEPTION_ACCESS_VIOLATION это unsigned long, unsigned long, char*) , И у этого подхода есть существенный недостаток: любое изменение числа, порядка или размера аргументов в ntdll.dll может нарушить ваш код.

Так что безопаснее и проще кодировать строки в ваш собственный код. Я считаю опасным использование строк, подготовленных кем-то другим, без согласования со мной :) и, более того, для других функций. Это еще одна возможность неисправности.

1 голос
/ 26 ноября 2008
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...