Exception seh sjlj что это
В чем разница между MinGW SEH и MinGW SJLJ?
Вопрос: что лучше установить и почему?
Решение
SJLJ и SEH — две разные системы обработки исключений.
Что касается конкретных различий, ресурсы, которые вы уже видели, охватывают все.
Однако, для чего лучше установить, идти с SJLJ если вы не знаете, что вам нужно SEH.
SJLJ более широко поддерживается в разных архитектурах и является более надежным. Кроме того, исключения SJLJ могут быть брошены через библиотеки, использующие другие системы обработки исключений, включая библиотеки C. Тем не менее, он имеет снижение производительности.
SEH гораздо более эффективен (без снижения производительности), но, к сожалению, не очень хорошо поддерживается. Исключения SEH приведут к возникновению плохих вещей, если их выбросить через библиотеки, которые также не используют SEH.
Что касается вашего кода, то никаких реальных отличий нет. Вы всегда можете переключить компиляторы позже, если вам нужно.
Другие решения
Я обнаружил одно различие между обработкой исключений SJLJ и SEH в MinGW-w64: обработчики сигналов C, установленные функцией signal (), не работают в версии SJLJ, как только хотя бы один блок try <> выполняется во время выполнения. Поскольку эта проблема, кажется, нигде не описана, я помещаю ее здесь для записи.
Следующий пример (test_signals.cpp) демонстрирует это.
Фактический вывод при сборке с вариантом MigGW-w64 SJLJ:
Приложение автоматически завершается после некоторой задержки. То есть обработчик сигнала не вызывается. Если блок try <> закомментирован, обработчик сигнала вызывается правильно.
При использовании варианта MinGW-w64 SEH он ведет себя как ожидалось (вызывается обработчик сигнала).
У меня нет четкого представления о том, почему возникает эта проблема, поэтому буду благодарен, если кто-то сможет дать объяснение.
What is difference between sjlj vs dwarf vs seh?
I can’t find enough information to decide which compiler should I use to compile my project. There are several programs on different computers simulating a process. On Linux, I’m using GCC. Everything is great. I can optimize code, it compiles fast and uses not-so-much memory.
I do my own benchmark with MSVC and GCC compilers. Later one produces slightly faster binaries (for each subarchitecture). Though compile time is much more than MSVC.
So I decided to use MinGW. But can’t find any explanation about exception handling methods and their implementations in MinGW. I can use different distributions for different operating systems and architectures.
2 Answers 2
There’s a short overview at MinGW-w64 Wiki:
Why doesn’t mingw-w64 gcc support Dwarf-2 Exception Handling?
The Dwarf-2 EH implementation for Windows is not designed at all to work under 64-bit Windows applications. In win32 mode, the exception unwind handler cannot propagate through non-dw2 aware code, this means that any exception going through any non-dw2 aware «foreign frames» code will fail, including Windows system DLLs and DLLs built with Visual Studio. Dwarf-2 unwinding code in gcc inspects the x86 unwinding assembly and is unable to proceed without other dwarf-2 unwind information.
GCC GNU about Exception Handling:
GCC supports two methods for exception handling (EH):
Structured Exception Handling (SEH)
Windows uses its own exception handling mechanism known as Structured Exception Handling (SEH). [. ] Unfortunately, GCC does not support SEH yet. [. ]
В чем разница между sjlj vs dwarf vs seh?
Я не могу найти достаточно информации, чтобы решить, какой компилятор должен использовать для компиляции моего проекта. На разных компьютерах существует несколько программ, имитирующих процесс. В Linux я использую GCC. Все прекрасно. Я могу оптимизировать код, он быстро компилируется и использует не так много памяти.
Я делаю свой собственный тест с компиляторами MSVC и GCC. Позже создается несколько более быстрые бинарные файлы (для каждой субархитектуры). Хотя время компиляции намного больше, чем MSVC.
Поэтому я решил использовать MinGW. Но не может найти никакого объяснения методов обработки исключений и их реализации в MinGW. Я могу использовать разные дистрибутивы для разных операционных систем и архитектур.
ОТВЕТЫ
Ответ 1
Вот краткий обзор на MinGW-w64 Wiki:
Почему mingw-w64 gcc поддерживает обработку исключений Dwarf-2?
Реализация Dwarf-2 EH для Windows не предназначена вообще для работают под 64-разрядными приложениями Windows. В режиме win32 исключение разматывающий обработчик не может распространяться через код, не поддерживающий dw2, это означает что любое исключение, проходящее через любые «внешние кадры», отличные от dw2, код не будет работать, включая системные DLL файлы Windows и библиотеки DLL, созданные с помощью Visual Studio. Код размотки гномов-2 в gcc проверяет x86 разматывать сборку и не может действовать без других карликов-2 раскрутите информацию.
GCC GNU об обработке исключений:
GCC поддерживает два метода обработки исключений (EH):
Обработка структурированных исключений (SEH)
Windows использует свой собственный механизм обработки исключений, известный как Structured Exception Handling (SEH). [. ] К сожалению, GCC пока не поддерживает SEH. [. ]
Ответ 2
Использование SEH в 32 разрядных приложениях Windows с компилятором Mingw-W64
Что такое SEH
Из всех механизмов, предоставляемых операционными системами семейства Windows, возможно наиболее широко используемым, но не полностью документированным, является механизм структурной обработки исключений (он же Structured Exception Handling, или просто – SEH). Структурная обработка исключений — это сервис, предоставляемый операционной системой, механизм обработки программных и аппаратных исключений в операционной системе Microsoft Windows, позволяющий программистам управлять обработкой исключений. Исключение — это событие при выполнении программы, которое приводит к её ненормальному или неправильному поведению.
Вся документация по SEH, которую вы, вероятно, найдете, описывает одну лишь компиляторно-зависимую оболочку, созданную функциями библиотеки времени выполнения (Run-Time-Library, RTL) вокруг реализации SEH операционной системы. В ключевых словах _try, _finally, или _except, нет ничего магического. Группы разработчиков из Microsoft, занимающиеся разработкой операционных систем и компиляторов, определили эти ключевые слова, и то, что они делают. Другие поставщики компиляторов просто поддержали эту семантику. Видимые программисту инструменты SEH уровня компилятора призваны скрыть базовый механизм SEH уровня операционной системы, что позволяет не обнародовать детали функционирования последнего. Основные детали базового механизма SEH уровня ОС будут рассмотрены в этой статье. В статье отражены личные взгляды и предпочтения автора.
Основной смысл SEH состоит в следующем: когда выполняющийся поток совершает ошибку, ОС дает возможность узнать об этом. Точнее, когда поток совершает ошибку, ОС приостанавливает поток, сохраняет все регистры процессора в специальной структуре и из служебного потока, связанного с тем, который вызвал ошибку, вызывает определенную пользователем callback-функцию. Функциональность этой callback-функции в значительной степени не регламентирована, т.е. в процессе своей работы она может делать все, что угодно. Например, она может устранить причину ошибки, если это возможно. Независимо оттого, что эта callback-функция делает, она должна возвратить значение, которое скажет системе, что делать дальше. Эта callback-функция называется exception handler(обработчик исключения). Для того, чтобы быть вызванной:
Технические детали SEH
Прототип функции обработчика исключения:
EXCEPTION_DISPOSITION это макроопределение, имеющее тип int, _EXCEPTION_RECORD содержит информацию о произошедшем исключении, EstablisherFrame — адрес структуры EXCEPTION_REGISTRATION в стеке потока, вызвавшего исключение, _CONTEXT — адрес структуры содержащей все регистры процессора в момент возникновения исключения, DispatcherContext — служебая информация
Структура данных EXCEPTION_REGISTRATION
Как видно из определения, структура состоит из 2х элементов по 32 бита, prev — адрес структуры с предыдущим обработчиком, handler — адрес функции обработчика исключения. Наличие элемента prev позволяет выстраивать цепочку из обработчиков, адрес последней структуры с актуальным обработчиком доступен через регистр fs:0, отсюда и начинается просмотр и вызов последовательности обработчиков, до тех пор, пока один из них не вернет значение ExceptionContinueExecution (0). Если ни один обработчик из цепочки обработчиков не может обработать исключение, то его обрабатывает первый элемент цепочки — обработчик исключений по умолчанию (стандартный обработчик), у которого нет варианта отказаться от обработки исключения.
SEH это ошибка
Я совершенно уверен в том, что сама изначальная идея SEH ошибочна. Операционная система будет сообщать программе о возникновении незапланированных «исключительных» ситуаций, таких как «деление на 0», «неверный HANDLE», «попытка исполнения неверной инструкции процессора» «попытка доступа к памяти при отсутствии соответствующих разрешений» и так далее. Совершенно нереально исправить такие ошибки во время исполнения программы, ошибка уже случилась, программа уже пошла по неверному пути, который привел ее к этой ошибке. Нельзя уже сделать ничего разумного, но SEH дает возможности:
К сожалению, стандартные обработчики ошибок современных ОС семейства Windows не показывают пользователю ничего, что могло бы информировать его о том, что случилось и что надо делать, после паузы и показа неинформативного окна приложение аварийно закрывается. Моя идея состоит в том, чтобы при возникновении исключения программист должен иметь возможность информировать пользователя об ошибке с помощью специально сформированных сообщений, после чего выполнить минимально возможную «приборку за собой» и постараться корректно закрыть программу. Еще раз напоминаю, что в большинстве случаев нормальное продолжение выполнения программы после возникновения исключения невозможно.
Компилятор GCC
GCC является главным компилятором для сборки ряда операционных систем; среди них — различные варианты Linux и BSD, а также ReactOS, Mac OS X, OpenSolaris, NeXTSTEP, BeOS и Haiku.
GCC часто выбирается для разработки программного обеспечения, которое должно работать на большом числе различных аппаратных платформ.
GCC является лидером по количеству процессоров и операционных систем, которые он поддерживает. Имеет развитые средства для программирования на встроенном ассемблере (ассемблерные вставки). Генерирует компактный и быстрый исполняемый код. Имеет возможности оптимизации, в том числе с учетом ассемблерных вставок. К относительным недостаткам GCC можно отнести непривычный синтаксис AT&T используемый во встроенном ассемблере.
GCC/MinGW является полностью надежным качественным компилятором, который, на мой взгляд, превосходит любой доступный на сегодняшний день компилятор языка Си по качеству сгенерированного кода. Это несколько менее выражено с самыми последними версиями MSVC, но все еще заметно. Особенно для всего, что связано с inline assembly, GCC на мой взгляд, превосходит MSVC.
Соответствие стандартам, как мне кажется, также намного лучше в GCC.
MinGW-W64 компилятор
MinGW— набор инструментов разработки программного обеспечения для создания приложений под Windows. Включает в себя компилятор, родной программный порт GNU Compiler Collection (GCC) под Windows вместе с набором свободно распространяемых библиотек импорта и заголовочных файлов для Windows API. В MinGW включены расширения для библиотеки времени выполнения Microsoft Visual C++ для поддержки функциональности C99.
В связи с тем, что в рамках изначального проекта MinGW не обещалось, что в его кодовую базу будут вноситься обновления, связанные с добавлением некоторых новых ключевых элементов Win32 API, а также наиболее необходимой поддержки 64-битной архитектуры, был создан проект MinGW-w64. Он является новой чистой реализацией портирования GNU Compiler Collection (GCC) под Microsoft Windows, осуществленной изначально компанией OneVision и переданной в 2008 году в общественное пользование (Public Domain). Сначала он был предложен на рассмотрение для интеграции с оригинальным проектом MinGW, но был отклонен в связи с подозрением на использование несвободного или проприетарного кода. По многим серьезным причинам этического характера, связанным с отношением со стороны авторов MinGW, ведущие разработчики кода MinGW-w64 решили больше не пытаться кооперироваться с проектом MinGW.
MinGW-w64 обеспечивает более полную реализацию Win32 API, включая:
Поддержка SEH в Mingw-w64
Совершенно неудовлетворительна поддержка SEH, проще сказать – ее нет, несмотря на наличие макросов __try1() и __except1. Мало того, что ни синтаксически (поскольку синтаксис __try __except() не поддерживается), ни семантически (макросы __try1 __except1 только позволяют установить/удалить обработчик исключений) невозможно программирование SEH, как с компиляторами Microsoft или Borland/Embarcadero, даже само использование макросов __try1 __except1 может приводить к проблемам
Проблемы
Использование стандартных макросов __try1 и __except1 может приводить к проблемам, так как в этих макросах явно изменяется состояние регистра ESP, но компилятор, который должен вести учет использования стека (что означает, что компилятор всегда должен «знать», каково значение регистра ESP), об этом не уведомляется. Может быть, стандартные макросы будут работать, а может быть и нет.
Решение
Во-первых, однозначно придется отказаться от использования стандартных макросов __try1 и __except1, вместо них будут ассемблерные вставки, не затрагивающие регистр ESP и локальная переменная типа EXCEPTION_REGISTRATION в стеке. Приблизительно вот так:
Во-вторых, необходимо отделить доверяемый код (т.е., отлаженный, не генерирующий исключений) от недоверяемого (где возможны исключения). Это достаточно стандартная практика, где за блоком try следует блок except С помощью нескольких глобальных переменных, ассемблерных вставок и имеющего дурную славу опрератора goto удалось решить такую задачу. Решение не претендует на универсальность, над этим еще надо думать, пока это выглядит как сваленный в кучу набор трюков. Недостатки: много ассемблерного кода, используются статические переменные, не производится «размотка» стека, состояние локальных переменных в стеке try блока теряется безвозвратно. Корректное завершение программы возможно, используя только переменные и функции из except блока.
От использования статических переменных, впрочем, легко отказаться, для чего придется «расширить» структуру EXCEPTION_REGISTRATION, дополнив ее недостающими элементами, перенести туда все бывшие ранее статическими переменные. Это сделает код примера не намного сложнее, но зато код будет по-настоящему структурным, способным обрабатывать исключения на нескольких уровнях вложенности. Доступ к дополнительным элементам расширенной структуры EXCEPTION_REGISTRATION_EX из функции обработчика исключения осуществляется через параметр EstablisherFrame который нужно преобразовать к соответствующему типу. Заодно сохраним значения регистров ESP и EBP, чтобы восстановить стек фрейм к тому состоянию, которое было в начале блока try. Теперь наш пример обретает законченную форму. К сожалению, при возникновении исключения, содержимое локальных переменных блока try безвозвратно теряется.
В чем разница между sjlj vs dwarf vs seh?
Я не могу найти достаточно информации, чтобы решить, какой компилятор должен использовать для компиляции моего проекта. На разных компьютерах существует несколько программ, имитирующих процесс. В Linux я использую GCC. Все прекрасно. Я могу оптимизировать код, он быстро компилируется и использует не так много памяти.
Я делаю свой собственный тест с компиляторами MSVC и GCC. Позже создается несколько более быстрые бинарные файлы (для каждой субархитектуры). Хотя время компиляции намного больше, чем MSVC.
Поэтому я решил использовать MinGW. Но не может найти никакого объяснения методов обработки исключений и их реализации в MinGW. Я могу использовать разные дистрибутивы для разных операционных систем и архитектур.
ОТВЕТЫ
Ответ 1
Вот краткий обзор на MinGW-w64 Wiki:
Почему mingw-w64 gcc поддерживает обработку исключений Dwarf-2?
Реализация Dwarf-2 EH для Windows не предназначена вообще для работают под 64-разрядными приложениями Windows. В режиме win32 исключение разматывающий обработчик не может распространяться через код, не поддерживающий dw2, это означает что любое исключение, проходящее через любые «внешние кадры», отличные от dw2, код не будет работать, включая системные DLL файлы Windows и библиотеки DLL, созданные с помощью Visual Studio. Код размотки гномов-2 в gcc проверяет x86 разматывать сборку и не может действовать без других карликов-2 раскрутите информацию.
GCC GNU об обработке исключений:
GCC поддерживает два метода обработки исключений (EH):
Обработка структурированных исключений (SEH)
Windows использует свой собственный механизм обработки исключений, известный как Structured Exception Handling (SEH). [. ] К сожалению, GCC пока не поддерживает SEH. [. ]