2008-11-26 20 views
8

Jak uzyskać nazwę i/lub opis wyjątku SEH bez konieczności sztywnego kodowania ciągów znaków w aplikacji?Jak uzyskać nazwę/opis wyjątku?

Próbowałem użyć FormatMessage(), ale obcina wiadomość czasami, nawet jeśli podasz ignorować wkładki:

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

Wywołuje wyjątek z kodem 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); 

Wypełnia msg ze ściętego wyrażenie: "The instruction at 0x".

+0

Wow to naprawdę wygląda na zepsute. Działa dla różnych wiadomości, ale nie mogę go uruchomić dla STATUS_ACCESS_VIOLATION na całe życie. – Charlie

+0

Jestem trochę zardzewiały, ale czy próbowałeś FORMAT_MESSAGE_FROM_SYSTEM? – morechilli

+0

morechilli: Tak, próbowałem już, ale to nie zmienia wyniku. – Sascha

Odpowiedz

2

strukturalne kod wyjątku są określone przez liczby NTSTATUS. Chociaż ktoś z MS suggests używający FormatMessage() do konwersji numerów NTSTATUS na ciągi znaków, nie zrobiłbym tego. Flaga FORMAT_MESSAGE_FROM_SYSTEM służy do przekonwertowania wyniku GetLastError() na ciąg, więc nie ma to sensu. Używanie flagi FORMAT_MESSAGE_FROM_HMODULE oraz ntdll.dll może prowadzić do nieprawidłowych wyników dla niektórych kodów. Np., Dla EXCEPTION_ACCESS_VIOLATION otrzymasz The instruction at 0x, co nie jest zbyt pouczające :).

Kiedy patrzysz na strunach, które są przechowywane w ntdll.dll staje się oczywiste, że wiele z nich mają być używane z funkcją printf(), a nie z FormatMessage(). Na przykład, łańcuch o EXCEPTION_ACCESS_VIOLATION jest:

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

%0 poddaje się obróbce FormatMessage() jak sekwencja ucieczki znaczenie komunikatu terminator nie wkładki. Wstawki to% 1 do% 99. Dlatego flaga FORMAT_MESSAGE_IGNORE_INSERTS nie robi żadnej różnicy.

Może chcesz załadować ciąg od ntdll.dll i przekazać go do vprintf ale trzeba będzie przygotować argumenty dokładnie jak Określa ciąg (np dla EXCEPTION_ACCESS_VIOLATION to unsigned long, unsigned long, char*). To podejście ma poważną wadę: każda zmiana liczby, kolejności lub rozmiaru argumentów w ntdll.dll może spowodować złamanie kodu.

Bezpieczniejsze i łatwiejsze jest zakodowanie łańcuchów w swój własny kod. Uważam, że używanie ciągów przygotowanych przez kogoś innego bez koordynacji ze mną jest niebezpieczne, a ponadto dla innych funkcji. To tylko jedna możliwość awarii.

+0

To jest tak zepsute, ale jest za późno na zmiany. – davidbak

+0

@davidbak Co jest zepsute? – 4LegsDrivenCat

+1

To, że mieli oni wszystkie okazje początkowo (gdy NT został utworzony), aby tworzyć właściwe ciągi dziennika zdarzeń (formatowanie stylu% 1), a zamiast tego tworzyli je w formacie printf. A potem nigdy nie dostarczyli nam substytutu. Muszą istnieć setki programów - jeśli nie tysiące - które mają specjalny kod do formatowania AV dla celów rejestracyjnych. – davidbak

Powiązane problemy