Это неявно вводимая компилятором переменная (типа ehstate) — состояние, по которому, в случае выброса исключения, обработчик определит, где оно произошло. "Оверхед" от этих команд очень мал по сравнению, например, с вызовом функции — на скорости цикла не скажется.
SEH фрейм регистрируется один раз — в прологе и снимается один раз — в эпилоге функции. В этом примере не видно, но можете проверять сами — картина останется неизменной независимо от количества вложенных try catch блоков. Будет лишь меняться значение ehstate — по сути, уровень вложенности. Если интересно, как работает обработчик, можно почитать статью Matt Pitreck в MSDN (есть перевод на wasm.ru) об обработке обычных (SEH) исключений компилятором MSVC. C++ EH работает примерно так же, только структура на стеке чуть меньше
Из принципиальных отличий от кода без исключений, я бы выделил невозможность инлайна:
1. дестракторов объектов из try блока;
2. самих функций с try блоком.
но тут еще вопрос, является ли это оверхедом, учитывая, что функция вызывается более одного раза...
Вывод такой — не стоит забивать голову ерундой об оверхеде. Нужно быть очень увереннымв себе, что бы писать под Win даже без __try __except, а C++ EH лишнего практически не вносит. Разве что копирование выброшенного объекта, если используется в обработчике (кстати, при ловле по ссылке — будет скопирована "ссылка"). А в x64 битной Win и SEH бесплатен.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Здравствуйте, gear nuke, Вы писали:
GN>Вывод такой — не стоит забивать голову ерундой об оверхеде. Нужно быть очень увереннымв себе, что бы писать под Win даже без __try __except, а C++ EH лишнего практически не вносит. Разве что копирование выброшенного объекта, если используется в обработчике (кстати, при ловле по ссылке — будет скопирована "ссылка"). А в x64 битной Win и SEH бесплатен.
. Не буду затрагивать высокоуровневые вещи, флейм vc коды возврата, и TR 18015.
[skip]
GN>Вывод такой — не стоит забивать голову ерундой об оверхеде. Нужно быть очень увереннымв себе, что бы писать под Win даже без __try __except, а C++ EH лишнего практически не вносит. Разве что копирование выброшенного объекта, если используется в обработчике (кстати, при ловле по ссылке — будет скопирована "ссылка"). А в x64 битной Win и SEH бесплатен.
Например, я — сверхупёртый Поэтому, если что-то расходится с моими взглядами (а если я что-то не знаю, то любая информация расходится), стараюсь проверить сам.
Предыстория поста: прочитал в MSDN, что C++ EH (стало быть и вообще C++ в общем случае) невозможно в ядре Windows. Одна из причин — огромный оверхед. Разобрался — на самом деле потому, что рантайм хранит немного хлама в TLS, которых в ядре нет, реализовал без него
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Здравствуйте, Максим2006, Вы писали:
М>Не сдержался?
Когда-то, в MSDN я читал в основном только первую половину описания функций — о параметрах. Потом заметил, что в какой-то вполне повседневной, в ремарках написано о необходимости __try.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
. Не буду затрагивать высокоуровневые вещи, флейм vc коды возврата, и TR 18015.
GN>Рассмотрим 2 примера для самого плохого случая из промышленных компиляторов — MSVC x86 (32bit).
GN>
Здравствуйте, gear nuke, Вы писали:
GN>Здравствуйте, Максим2006, Вы писали:
М>>Не сдержался?
GN>Когда-то, в MSDN я читал в основном только первую половину описания функций — о параметрах. Потом заметил, что в какой-то вполне повседневной, в ремарках написано о необходимости __try.
Напиши, плиз, в какой, если вспомнишь.
А так, не только ж из-за оверхеда отказываются от исключений (например, в ком) и "писать под Win" — очень уж широкое понятие.
Здравствуйте, merk, Вы писали:
M>пример не очень показательный.
Пример такой, что бы было похоже на пост по ссылке.
M>сделайте так M>есть функция, что кидает 2 разных исключения M>вызиывется в простом цикле. M>после цикла есть обработчик одного и другого исключения.
Вот сам бы сделал, и увидел бы, что количество throw и catch не повлияет на размер лишнего кода (рузумеется, будет добавлен код для каждого catch и по вызову 2х аргументной функции на каждый throw). Хендлер будет всё равно один (он вообще один на всю программу и вызывается через переходники, см. ниже) и искать нужный catch в статической таблице (по типу брошенного объекта).
В простых случаях, с /EHs, компилятор вообще может разрулить все без SEH, на условных переходах.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Здравствуйте, Максим2006, Вы писали:
М>Напиши, плиз, в какой, если вспомнишь.
Написал в "какой-то", потому что она не одна. Например, MapViewOfFile.
М>А так, не только ж из-за оверхеда отказываются от исключений (например, в ком) и "писать под Win" — очень уж широкое понятие.
Я мало знаком с COM, вот что нашел:
COM will not propagate a C++ exception from the callee to the caller, even when both the caller and the callee are written in C++. This catches some COM newcomers off guard, but it should be no surprise if you recall that COM is language-independent. COM boundaries are language boundaries. After all, if the caller is written in C and the callee is written in C++, what would COM do with the C++ exception? If your code throws an exception, the caller will see a failure with an HRESULT of 0x80010105 (RPC_E_SERVERFAULT). Interestingly enough, this is the same error the caller sees if the callee attempts an illegal memory access. In both cases, the COM runtime isolates the caller of the object from runtime errors inside the object and presents them as server errors.
Это ведь не запрет, а ограничение?
Кстати, С++ рантайм зачем-то понимает исключение с NTSTATUS 0xE0000000|'MOC' (C++ имеют код 0xE0000000|'msc')
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Здравствуйте, merk, Вы писали:
M>сделайте так M>есть функция, что кидает 2 разных исключения M>вызиывется в простом цикле. M>после цикла есть обработчик одного и другого исключения.
M>типа псевдокод.
подумалось еще вот что -- интересно, а как влияет на быстродействие "вложенность" try/catch?
Здравствуйте, Alexander G, Вы писали:
AG>А почему MSVC x86 — самый плохой случай из промышленных компиляторов ?
В нём C++ EH реализован поверх SEH OS, генерируются дополнительные машинные команды для инициализации хендлеров (см. пролог функции). ICC для Win32 тоже попадает сюда, т.к. он бинарно совместим. Это разумная плата за возможность ловить и низкоуровневые исключения + возможность трансляции их в C++.
В GCC, если не ошибаюсь, сделано как и в Win64, без оверхеда в рантайме на инициализацию (data approach согласно TR 18015).
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Здравствуйте, gear nuke, Вы писали:
GN>Здравствуйте, Максим2006, Вы писали:
М>>Напиши, плиз, в какой, если вспомнишь.
GN>Написал в "какой-то", потому что она не одна. Например, MapViewOfFile.
На on-line MSDN для MapViewOfFile нет вроде упоминаний о __try/__catch
М>>А так, не только ж из-за оверхеда отказываются от исключений (например, в ком) и "писать под Win" — очень уж широкое понятие.
GN>Я мало знаком с COM, вот что нашел: GN>
COM will not propagate a C++ exception from the callee to the caller, even when both the caller and the callee are written in C++. This catches some COM newcomers off guard, but it should be no surprise if you recall that COM is language-independent. COM boundaries are language boundaries. After all, if the caller is written in C and the callee is written in C++, what would COM do with the C++ exception? If your code throws an exception, the caller will see a failure with an HRESULT of 0x80010105 (RPC_E_SERVERFAULT). Interestingly enough, this is the same error the caller sees if the callee attempts an illegal memory access. In both cases, the COM runtime isolates the caller of the object from runtime errors inside the object and presents them as server errors.
GN>Это ведь не запрет, а ограничение? GN>Кстати, С++ рантайм зачем-то понимает исключение с NTSTATUS 0xE0000000|'MOC' (C++ имеют код 0xE0000000|'msc')
Ага, ограничение, ограничивающее использование исключений поэтому и отказываются
Здравствуйте, varnie, Вы писали:
V>подумалось еще вот что -- интересно, а как влияет на быстродействие "вложенность" try/catch?
Практически никак не влияет. Я уже упоминал выше про ehstate — грубо, каждому try присвается свой номер и он сохраняется на входе в блок командами
mov DWORD PTR __$EHRec$[ebp+12], 0
Количество catch влияет на размер данных (по 16 байт на каждый). В рантайме оверхед == 0 — затраты только если возникло исключение.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
GN>Вывод такой — не стоит забивать голову ерундой об оверхеде. Нужно быть очень увереннымв себе, что бы писать под Win даже без __try __except, а C++ EH лишнего практически не вносит. Разве что копирование выброшенного объекта, если используется в обработчике (кстати, при ловле по ссылке — будет скопирована "ссылка"). А в x64 битной Win и SEH бесплатен.
Вы тут не упомянули самую малость
А конкретно то что бросание исключения это вызов ядра, и последующий callback из ядра user-mode обработчика (ntdll!KiUserExceptionDispatcher) который уже начнет бродить по структурам в TEB'е вызывая обрабочики. И пара тысяч тактов CPU на всю эту мудотень.
Здравствуйте, gear nuke, Вы писали:
GN>Здравствуйте, merk, Вы писали:
M>>пример не очень показательный.
GN>Пример такой, что бы было похоже на пост по ссылке.
M>>сделайте так M>>есть функция, что кидает 2 разных исключения M>>вызиывется в простом цикле. M>>после цикла есть обработчик одного и другого исключения.
GN>Вот сам бы сделал, и увидел бы, что количество throw и catch не повлияет на размер лишнего кода (рузумеется, будет добавлен код для каждого catch и по вызову 2х аргументной функции на каждый throw). Хендлер будет всё равно один (он вообще один на всю программу и вызывается через переходники, см. ниже) и искать нужный catch в статической таблице (по типу брошенного объекта).
честно говоря, я настолько морально устойчив, что не применяю некие прынципы, только исходя из кода, что генерит для них компилятор. пользоваться парадигмами нужно тогда, когда они логически уместны, и каким-то образом упрощают и далают наглядной ту систему высказываний, которой является программа. вообще, не взирая на оверхед.
а критиковал я пример только потому, что он не иллюстрирует реальное применение исключений, когда происходит обработка какого-то конкретного исключения, а не ВСЕХ. что есть просто перехват трэпа.
Здравствуйте, Аноним, Вы писали:
GN>>Вывод такой — не стоит забивать голову ерундой об оверхеде. Нужно быть очень увереннымв себе, что бы писать под Win даже без __try __except, а C++ EH лишнего практически не вносит. Разве что копирование выброшенного объекта, если используется в обработчике (кстати, при ловле по ссылке — будет скопирована "ссылка"). А в x64 битной Win и SEH бесплатен. А>Вы тут не упомянули самую малость А>А конкретно то что бросание исключения это вызов ядра, и последующий callback из ядра user-mode обработчика (ntdll!KiUserExceptionDispatcher) который уже начнет бродить по структурам в TEB'е вызывая обрабочики. И пара тысяч тактов CPU на всю эту мудотень.
Дык он разбирал накладные расходы в случае, если исключение не будет брошено. А ежели оно будет брошено — то какая разница где стоит try/catch ? В любом случае будет расход кучи тактов.
Здравствуйте, merk, Вы писали:
M>честно говоря, я настолько морально устойчив, что не применяю некие прынципы, только исходя из кода, что генерит для них компилятор.
Значит этот пост был адресован другим.
M>пользоваться парадигмами нужно тогда, когда они логически уместны, и каким-то образом упрощают и далают наглядной ту систему высказываний, которой является программа. вообще, не взирая на оверхед.
В "философии програмирования" я бы охотно согласился, а, например, ISO/IEC составили Technical Report on C++ Performance где Exception Handling посвещен десяток страниц. Там люди штаны просиживают.
M>а критиковал я пример только потому, что он не иллюстрирует реальное применение исключений, когда происходит обработка какого-то конкретного исключения, а не ВСЕХ.
Что бы более-менее раскрыть тему C+ EH в MSVC, нужно минимум статью по объёму как у Pietrek (эх, опесатался выше ) и Jorgon, да 1K+ LOC. Без учета Re: Правда об оверхеде исключений.
Только чукча не писатель, чукча лесом едет, лес поёт
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Здравствуйте, IID, Вы писали:
IID>В любом случае будет расход кучи тактов.
А главное, что это будет в исключительной ситуации
P.S. ты куда пропал
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Здравствуйте, gear nuke, Вы писали:
GN>Здравствуйте, IID, Вы писали:
IID>>В любом случае будет расход кучи тактов.
GN>А главное, что это будет в исключительной ситуации
Меня интересует с какой скоростью сервер будет обрабатывать запросы, меня не интересует с какой скоростью он не будет обрабатывать запросы.