Вот такая ситуация. Собираю DLL без использования MSVCRT. При сборке стоит флаг /SAFESEH:NO. В коде устанавливаю SEH стандартным образом: Код (Text): LPDWORD lpData = NULL; VOID handler() { *lpData = (LPVOID)&lpData; } ... __asm { int 3 } __asm { push offset handler push fs:[0] mov fs:[0], esp } *lpData = 0; __asm { mov eax, [esp] mov fs:[0], eax add esp, 8 } ... Так вот, после загрузки DLL попадаю на int3. Оттуда прохожу под отладчиком установку SEH-обработчика handler. Но при выполнении *lpData = 0 выскакивает сообщение: "Unhandled exception at 0x005a1066 in dll-loader.exe: 0xC0000005: Access violation writing location 0x00000000." Уже всю голову себе сломал, почему не иксепшн обрабатывается... Кто знает, подскажите пожалуйста в чём дело может быть?... Спасибо.
Забыл ещё вот что сказать. Если вместо 'push offset handler' поместить 'push 0deadc0deh', то получается вот это: "Unhandled exception at 0xdeadc0de in dll-loader.exe: 0xC0000005: Access violation."
и это всё? Код (Text): push offset SEH_proc ; Адрес обработчика SEH push fs:[0] ; Адрес предидущего обработчика SEH mov fs:[0], esp ; Установить свой SEH ... ;========================= Обработчик SEH ================================== SEH_proc proc C uses ebx edi esi, pExcept: dword, pFrame: dword, pContext: dword, pDispatch: dword ... mov eax, ExceptionContinueExecution ; Флаг продолжить выполнение программы ret SEH_proc endp
Код (Text): DWORD handler(DWORD, DWORD, DWORD, DWORD) { lpData = (LPDWORD)&lpData; return ExceptionContinueExecution; } Как-то без изменений... Я так думаю, что дело не в обработчике. Проверял до этого.
Кстати, набросал обработку точно такого же случая на masm32 - всё работает. Причём, в handler такой же простенький, как у меня был. Тут что-то именно с DLL и с MSVC....
Да, забыл вот ещё что отметить - загрузка DLL происходит без использования LoadLibrary. Как обычно разбирается заголовок, выделяется память, переносятся и настраиваются секции, импорты и т.д. Затем, вызывается DllMain. Может быть это ключ к ответу?..
А в дизасме это смотрел? С компилятор вообще-то может использовать для возврата не только eax, а любой понравившийся ему регистр.
По-моему так надо(в этой сказке против правил кто-то строчки переставил): Код (Text): push fs:[0] ; Адрес предыдущего обработчика SEH push offset SEH_proc ; Адрес обработчика SEH mov fs:[0], esp ; Установить свой SEH
gorodon нет с порядок push не верный у тебя. Мой пример на asm выше полностью рабочий 7mm Действительно странно Код (Text): LPDWORD lpData = NULL; DWORD handler() { *lpData = (DWORD)&lpData; return ExceptionContinueExecution; } // Начало основной программы void myMain(void) { // __asm { int 3 } __asm { push offset handler push fs:[0] mov fs:[0], esp } *lpData = 0; __asm { mov eax, [esp] mov fs:[0], eax add esp, 8 } Компилится в Код (Text): 00401000 . A1 64304000 MOV EAX,DWORD PTR DS:[403064] ; Structured exception handler 00401005 . C700 64304000 MOV DWORD PTR DS:[EAX],Small_W3.00403064 0040100B . 33C0 XOR EAX,EAX 0040100D . C3 RETN 0040100E CC INT3 0040100F CC INT3 00401010 >/$ 56 PUSH ESI ; <-- точка входа программу 00401011 |. 68 00104000 PUSH Small_W3.00401000 ; SE handler installation 00401016 |. 64:FF35 000000>PUSH DWORD PTR FS:[0] 0040101D |. 64:8925 000000>MOV DWORD PTR FS:[0],ESP 00401024 |. A1 64304000 MOV EAX,DWORD PTR DS:[403064] 00401029 |. C700 00000000 MOV DWORD PTR DS:[EAX],0 0040102F |. 8B0424 MOV EAX,DWORD PTR SS:[ESP] 00401032 |. 64:A3 00000000 MOV DWORD PTR FS:[0],EAX 00401038 |. 83C4 08 ADD ESP,8 т.е. обработчик SEH нормальный и оля распознаёт его установку но при установке бряка на 00401000 после исключения и Ctr F9 в этот бряк не попадаем, как будто и нет никакого сеха... Странно. ---- Кстати заметь если с этим удастся разобраться возникнет другая заморочка: *lpData = 0; превращается в 00401024 |. A1 64304000 MOV EAX,DWORD PTR DS:[403064] 00401029 |. C700 00000000 MOV DWORD PTR DS:[EAX],0 соответсвенно исключение происходит на второй строке этого кода, т.е. в обработчике нужно исправлять pContext.regEax, а для этого нужно быть уверенным что компилятор здесь использует именно eax )
7mm я не про это - у меня тоже (/NODEFAULTLIB), а про: т.е. ключ к ответу точно не здесь. И главное как я показал выше самостотельная реализация SEH под C не столь тривиальна как кажется на первый взгляд (ты исправляешь переменную, а нужно исправлять регистр, да ещё угадать какой . Поэтому вопрос ребром - а стоит ли овчинка выделки? Может лучше такие вещи целиком на асме или на родном для С цртшном SEH механизме делать? вместо такой труднопредсказуемой гремучей смеси.
Мне не нужна CRTL так же как не нужна полноценная обработка исключений, достаточно того, чтобы они просто ловились через __try // __except , __try // __finally.