| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Общие вопросы > Fail |
| Автор: pascal 29.3.2004, 03:06 | ||||||||
| Может кто знает почему когда я вызываю Fail в конструкторе класса, которой создаёться вне try при завершении программы возникает ошибка... Пример:
если я в dpr проекте попытаюсь создать объект и если Fail будет выполнена, то либо при создании проекта будет ошибка, либо при завершении работы возникнет ошибка, причём в модуле system в процедуре UnsetExceptionHandler... Например:
будет ошибка а если вот так
или так
то всё ок... Но почему??? (для тех кто не знает: Fail может быть вызвана в функции типа constructor и она удаляет созданный объект из памяти и TObject.Create возврощает nil) PS: Не надо предлагать перенсти этот фрагмент кода в try, как это в работоспособных примерах, меня суть ошибки интересует... |
| Автор: p0s0l 29.3.2004, 06:54 | ||||||
| В D7 сразу видно, что компилится по-левому, т.к. esp не восстанавливается... Пример:
Компилится так:
Видно, что после add esp, -$10 надо бы его как-то восстановить, но Fail без раздумьев прыгает на pop esi, pop ebx, ret так и не восстановив esp... Остюда и вся лажа... Для данного случая можно сделать свой Fail:
add esp, $14 - это из-за того, что в конструкторе делали add esp, -$10 и вызывали MyFail (4 байта в стеке)... Добавлено @ 06:56 pascal, тебе же может надо будет делать не $14, а побольше (но кратно 4). Посмотри у себя, насколько портится esp... Добавлено @ 06:58 А, да, еще может не только pop esi, pop ebx делать надо, но и еще какой-нибудь pop - посмотри код твоего конструктора (в отладке View->Debug Windows->CPU window)... |
| Автор: pascal 29.3.2004, 15:08 | ||||
нет, в чём то другом дело... делаю так
всё равно не работает, ошибка там же... то есть вот так
всё равно там же ошибка |
| Автор: pascal 29.3.2004, 15:34 | ||
> DB := TDB.Create;
при выполнении последней строки изменяються регистры: EAX - 00466A74 -> 00000000 EBX - 7FFDF000 -> 0012FFA0 ECX - 0012FF9C -> 00000000 EDX - 0012FF01 -> 00000000 ESI - 00000000 -> 004671C2 EDI - 00000000 -> 0012FF48 |
| Автор: pascal 29.3.2004, 22:13 | ||
вроде работает, но как всётаки без этого обойтись??? |
| Автор: p0s0l 30.3.2004, 13:24 | ||||||||
pascal, ошибка-то возникает в конструкторе, зачем push и pop делать где-то там, в далеке ? Что, каждый раз так будешь делать ? Я же привел пример, как исправить сам конструктор (вместо Fail делать MyFail)... Приведи асм-листинг самого конструктора (начиная с begin) - я тебе напишу, как у тебя будет выглядеть MyFail. Ошибка возникает, как я сказал, из-за того, что esp при Fail не восстанавливается, а значит pop esi и pop ebx (в приведенном примере) восстанавливаются совсем по-левому, и, самое главное, ret происходит неизвестно куда, может в космос, из-за этого и появляется исключение... Добавлено @ 13:30
Ага, зачем try..except заменять на asm-аналог ? Быстрее try-except написать, чем всё это, и будет то же самое... |
| Автор: pascal 30.3.2004, 13:49 | ||||||
Я придумал, вот так работает
тока в теле try слишком сильно сбиваеться esp и восстановить его весьма сложно то есть вот так уже работать не будет
или
|
| Автор: p0s0l 30.3.2004, 15:52 |
| А зачем pop dword ptr fs:[0] ? Это же в случае try..except... Просто add esp, $10 не работает ? |
| Автор: pascal 30.3.2004, 23:27 | ||
Неа, не работает... В FS:[0] Delphi переодически esp сохраняет... а сам esp и с "add esp, $10" и без него не меняеться в результате... |
| Автор: p0s0l 31.3.2004, 06:46 | ||||||
Если ты пользуешь try - тогда и сохраняет...
Esp в обоих случаях будет одинаковым, к твоему сведению 1. add esp, $10 2. add esp, $0c; pop dword ptr fs:[0] Так что что-то ты там намудрил, или неправильно понял... pop dword ptr fs:[0] не восстанавливает esp, а заносит по этому адресу fs:[0] dword из стека. Вот способ Fail, работающий хоть в try..except, хоть без него:
|