Просто хаккескими штучками не увлекаюсь, а для построения безглючного и эффективного приложения - достаточно того механизма что я себе придумал. Более того, подозреваю что мой механизм наипрост и наиэффективен, в обратном пока меня никто не убедил. По-любому что-то делать надо - не складывать же лапки... Например поставить флаг того что произошло, eip передвинуть на следущую инструкцию, проверяющую флаг... Я как раз в SEH ничего не обёртываю. Мои обёртывающие макросы try-except никакого кода не добавляют, в [FS:0] не лезут, просто помещают текущий адрес в список, и следом за ним адрес обработчика. А повторять такой хандлер для каждой div - действительно нет смысла - я его сделаю один, перед div не буду ставить try, просто сам div будет макросом, заносящим в список к своему адресу указатель на div-handler общий для всех. Так и я про то-же - нефих ничего откатывать - главное не дать виндовсу повода закрыть процесс, сказать ему "всё хоккей, продолжаем", вернуть тому кто вызывал статус ошибки - пусть разбирается, пробует с другими параметрами, или тоже возвращает на верх статус ошибки и так далее пока не дойдёт до того кто виновен в неправильных данных. Тот же самый откат только не в процессе обработки исключения, а в рамках нормального разумного взаимодействия процедур. У меня такое мнение - эти раскрутки и откаты придумали разработчики ВУ-языков от неспособности компилировать процедуры с более менее разумным взаимодействиям по возникновении ошибок, им показалось что решить все проблемы можно каким-то тупым механическим откатом состояний. Но нифига толком не вышло, а этот механихм SEH так и остался лежать грузом на мозгах прогрммистов и производительности компьютеров. Мне лично, на ассемблере, ничто не мешает закодить процедуры так чтобы они сами сознательно исправляли, освобождали занятые ресурсы и т.п. - тот же откат, только не тупой, а осмысленный... Мне от ОС надо только чтоб вызвала мою единственную точку входа в обработчик с инфой о том где и что. Если б не этот грёбанный сех - вызов единственного обработчика исключений потока происходил бы гораздо быстрее.
gas Вот именно в этом и вопрос заключается, необходимо вначале продумать архитектуру, только затем реализовать. На следующую инструкцию управление нельзя передать, очевидно. Иначе получится виртуальная машина(div будет выполнять дополнительную обработку данных), принципы которой уже давным давно отработаны и используются очень широко. Да и код вырастет до размеров, больших, чем при заключении блоков в сех. Добавите виртуальныю Jcc после каждой инструкции или напишите макро, вставляющее ветвление с необходимым условием, зависящим от инструкции ? Например так. Исходный код: Код (Text): mov eax,dword ptr ss:[ebp + 0x14] mov ecx,dword ptr ds:[eax + 4] mov dword ptr ss:[ebp - 0x34],ecx movzx edx,word ptr ds:[eax] Виртуальный: Код (Text): mov eax,dword ptr ss:[ebp + 0x14] jz Fault1 ; ZF предыдущая инструкция не должна изменять. mov ecx,dword ptr ds:[eax + 4] jz Fault2 cmp eax,ecx %JFAULT Fault3 ; Макро, так как флагов не хватает. Либо анализ следующих изменяемых флагов на этапе написания кода. mov dword ptr ss:[ebp - 0x34],ecx movzx edx,word ptr ds:[eax] jc Fault4 Я таким игрался много лет назад, когда только начинал изучать архитектуру Нормальный код имеет следующую структуру: Код (Text): SUB(): %SEH_PROLOG Ip1: #XCPT ... Ip2: #XCPT %SEH_EPILOG ... Если есть захваченные ресурсы, то перед их освобождением блок заключается в сех, иначе он общий для всех инструкций блока(процедуры): Код (Text): SUB(): %SEH_PROLOG Ip1: #XCPT %SEH_EPILOG ... %SEH_PROLOG Ip2: #XCPT %SEH_EPILOG ... Где сех общий для всех прологов. У вас же тоже, только без доступа к ресурсам(тоесть нет смысла, так как нет ресурсов, требующих освобождения). Причём сехи всех прологов разные. Что вы обьединили в массив векторов с целью оптимизации: Код (Text): SUB(): Ip1: #XCPT ... Ip2: #XCPT IPTABLE{ Ip1, @SEH1 Ip2, @SEH2 А сам код заключён в один единственный сех пролог: Код (Text): %SEH_PROLOG SUB() %SEH_EPILOG Учитывая что вы не знаете что будите делать в каждом сех, дальнейшее рассмотрение затруднительно. Очевидно что незачем вводить проверки виртуальных флагов, после которых идет Jcc Exit из процедуры, если можно это всё сделать безо всяких там VM инструкций, просто возвратившись из сех на безопасное место, выполняющее возврат из процедуры(посмотрите как выглядит осевой код =)). Код (Text): %SEH_PROLOG1 Reference() ; Захват ресурса. %SEH_PROLOG2 #XCPT %SEH_EPILOG Dereference() ; Освобождение ресурса. %SEH_EPILOG Если код, генерящий фолт после захвата ресурса, не использует локальный сех(2), то ресурс не будет освобождён.
klzlk, я не собираюсь защищать абсолютно всё где потенциально, в следствии глюка, могут оказаться недопустимые значения. Защищать надо только те инструкции для которых я умышленно допускаю исключение. Их во всей программе совсем немного и ничего от этого не раздуется. А с глюками бороться на лету - бессмысленно. При непредвиденном исключении может быть только одна задача - записать в лог имя сглючившей процедуры, и добровольно завершить процесс. Чтобы найти имя, у меня макросы типа proc тоже создают список адресов процедур и их имён. Кроме того, начало работы каждой процедуры отмечается в глобальной переменной, путём занесения в неё своего адреса. При неожиданном исключении (когда в списке ожидаемых не оказалось адреса исключения), по значению этой переменной и адресу исключения можно определить в какой процедуре исключение и была ли в ней выполнена инструкция с недопустимым адресом или ещё чего, или управление из неё куда-то улетело и стало причиной недопустимой операции в другом месте. Этого мне достаточно для отладки. И никаких заморочек с SEH мне не надо.
gas Вам уже целую страницу пытаются обьяснить, что если в процессе работы с выделенным ресурсом происходит исключение, то в обработчике этот ресурс должен быть освобожден. Подумайте внимательно над последним псевдокодом Код (Text): %SEH_PROLOG1 Reference() ; Захват ресурса. %SEH_PROLOG2 #XCPT %SEH_EPILOG Dereference() ; Освобождение ресурса. %SEH_EPILOG
K10 я тоже целую страницу пытаюсь объяснить что если при работе хоть с каким ресурсом произошло неожиданное исключение - лучше сделать что можно для сохранения данных, записать что-то в лог для отладки и добровольно закончить процесс, а ОС сама освободит все связанные с ним ресурсы. Все эти попытки чего-то там откатить, вернуться к нормальной работе - от лукавого. Неожиданных исключений не должно быть в принципе. Если они есть - надо отлаживать код, а не "делать хорошую мину при плохой игре". Ожидаемые исключения - другое дело и для их обработки не нужно никаких нештатных освобождений ресурсов, раскруток, откатов и прочей ерунды.