информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Spanning Tree Protocol: недокументированное применениеЗа кого нас держат?Атака на Internet
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Крупный взлом GoDaddy 
 Просроченный сертификат ломает... 
 Phrack #70/0x46 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
Я в общем не понял вопроса, но в exception-ах разбираюсь неплохо 08.05.07 11:55  Число просмотров: 2526
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
Разве что ни фига не понимаю чем отличаются /EHs от /EHa (но я предпочитаю синхронный вариант - /EHs)

> Я просмотрел форумы MSDN. Меня смутило, что народ,
> причисляющий себя чутли не к разработчикам в Microsoft,
> зачастую имеет противоположные точки зрения.
> Одни говорят, мол, очень плохая идея компилировать с /EHa
> (никто не обьясняет, почему плохая идея, наверное, ссылка
> на статью MSDN, где только вскользь сказано овозможных
> оверхедах - по дефолту в голове). Другие окологуру


Оверхед на x86 платформе: пара десятков байт на стеке и прилинковывание нового фрейма к списку обработчиков в fs:0 плюс еще постоянный апдейт номера состояния при появлении новых локальных переменных (которые надо будет деструктить в случае раскрутки стека). А если еще учесть, что независимо от количество CE-шных try блоков в фукнции компилятор генерит только один SE-шный __try блок, то оверхэд может быть и отрицательным. Короче, практически нет оверхеда при отсутствии собственно самих ислкючительных ситуаций. Но вот если исключение таки бросается, то производится туева хуча работы, причем большая часть работы не зависит от того используется ли SE или CE (CE - это просто надстройка над SE). Но ситуации на то и исключительные, что не должны появляться часто. Поэтому их эффективность в удобстве доставки информации от места где произошло исключение к месту, где оно может быть обработано, а не в миллионах эксепшенов в секунду. По этому показателю CE однозначно лучше.

> (kenguru?) говорят, мол компилируй только с /EHa.
Компилируй с /EH :-)

> Наиболее здравый взгляд, мне кажется, у Рихтера. Он пишет,
> что сам он предпочитает вылавливать Win32 SE в
> __try/__except если надо, a затем транслировать SE в CE C++
> _set_se_translator ...

Чего то не того. __CxxFrameHandler проверяет по сигнатурам является ли exception C++сным и если нет, то вызывает se_translator (если он был установлен). А этот самый __CxxFrameHandler устанавливается хэндлером для try-catch блоков и генерится автоматом. В принципе, если ты отловил в __except исключение, которое брошено через throw, то в принципе нет нормального способа превратить его обратно в CE. Ловить надо в try-catch, а установленный se_translator (который при необходимости будет вызван обработчиком фрейма) должен перебросить SE в виде CE (вот здесь двойной оверхэд и по памяти и по времени обработки).

> Мне кажется что в VC 6.0 это не актуально ... Нет ...
> вроде актуально.

Актуально. EH практически не менялся со времен как минимум NT4.0 (скорее всего даже еще раньше).
<programming>
[C++] /ЕHa или /EHsc 23.04.07 07:31  
Автор: void <Grebnev Valery> Статус: Elderman
Отредактировано 23.04.07 07:35  Количество правок: 1
<"чистая" ссылка>
Вопрос о "накладных расходах" при включении в код __try/__except и компиляции с /ЕHa или /EHsc. "Накладные расходы" по размеру приложения и, что самое главное, по скорости желательно получить маленькие. Пример кода, некоторая статистика и выводы приведены ниже. Поделитесь, пожалуйста, опытом.

Надо "обернуть" имеющееся API (например, API MySQL, разработаное на С) в C++. Обёртки будут использоватьcя в приложениях VC++6.0/8.0 3-х типов: STL; STL+MFC; MFC.

Исключительные ситуации, увы, не обрабатываются API :(
Для этого сделан класс:
class CMySqlException : public std::exception который throw CMySqlException(param) в вызывающий код.

Например:

class CMySqlDataReader
{
...
public:
bool Read()
{
TRY_SEH
m_curr_row = mysql_fetch_row(m_result);
ON_CATCH_SEH ( throw CMySqlException (m_handle);)
return (m_curr_row != NULL);
}
...
};

Здесь
mysql_fetch_row - одна из функций API, которая может "анормал терминайте программ", если не обработать еxception (например, m_result == NULL или содержит мусор)

TRY_SEH\ON_CATCH_SEH определены следующим образом:

#defineSEH
#ifdefSEH
#define TRY_SEH __try {
#define ON_CATCH_SEH(_expressions) } __except(EXCEPTION_EXECUTE_HANDLER) { _expressions; }
#else
#define TRY_SEH ((void)0);
#define ON_CATCH_SEH(ex) ((void)0);
#endif

Тестировалось простейшее приложение MySQL (локально), скомпилированное в 4-версиях:
1) /EHsc и //#defineSEH(__try/__except не использовалось)
2) /EHsc и #defineSEH(__try/__except использовалось)
3) /EHа и //#defineSEH(__try/__except не использовалось)
4) /EHа и #defineSEH(__try/__except использовалось)

Тестирование показало:

1) Не обнаружено сколь-нибудь заметной разницы в скорости выполнения кода для всех 4-х вариантов. Это можно обьяснить тем, что ботлнэк в данном примере - это обращение к базе данных (хоть бы и локально). По идее же, включение /EHа или __try/__except должно было б замедлить программу. Причём, /EHа должно бы оказывать глобальное и более ошутимое влияние.

2)Размер "релиза" оказался: 16Кбт (1), 32Кбт (2,3), 19Кбт (4). Это трудно обьяснить, когда для /EHa явное включение в код __try/__except привело к уменьшению размера кода, а не увеличению. Разве, что компилятор так оптимизирует код.

3) Вопреки ожиданиям, /EHa без явного __try/__except (3), всёже "пропускает" некоротые exceptions, не перенаправляя их в C++ try/catch(std::exception& error).
Однако, как и обещано Microsoft, эти exceptions ловятся в catch(...). От этого может немного усложнится обработка (re-throw) в проложениях MFC.

4) И /EHa, и /EHsc в сочетании с __try/__except (2,4) всегда перенаправляют exceptions в C++ try/catch(std::exception& error) как и в catch(CMySqlException &ех). Это хорошо для приложений MFC.

Выводы:

1) Обязательно использовать __try/__except в критичных учацтках кода вне зависимости используется /EHa, или нет. Иначе /EHa может перенаправлять exception в catch(...) вместо catch(CMySqlException &ех) и вместо catch(std::exception& error). Это может быть критично для приложений MFC, где обработка виполняетя в коде типа:

TRY{...}
CATCH_ALL(e) {
CMySqlException dbe;

if ( e->IsKindOf(RUNTIME_CLASS(CMySqlException ) ))
{
CMySqlException *pAfxDbex = (CMySqlException *) e;
...
}
else
{
...
}
AfxThrowLastCleanup();
throw dbe;
}
END_CATCH_ALL

2) Заманчиво использование /EHa. Поскольку в сочетании с явным включением __try/__except на критических участках кода, это только придаст большую надежность коду:
- пропущеные программистом "С" SHE все равно будут в catch(...)
- не пропущеные в __try/__except "С" SHE будут re-throw и "попадутся" в catch(CMySqlException &ех) или catch(std::exception& error) в вызывающем коде.

Сомнения здесь относительно приложений MFC. Я не проводил теститования приложений MFC, скомпилированных с /EHa. Кроме того, поскольку /EHa оказывает глобальное влияние на весь проект, то не ясно какие оверхеды могут возникнуть.

Короче простой вопрос: кто как делает, когда приложение представляет смесь
API "C", STL, MFC?

Спасибо.
Поскольку никто не отвечает сразу оговорюсь, что, конечно,... 03.05.07 03:29  
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
Поскольку никто не отвечает сразу оговорюсь, что, конечно, при /EHa
в VC 8.0 C++ SE экзепшн ловится в функции обработчике C++ класса определённой _set_se_translator( _translateSEtoCE) (надо вызываеть в начале каждого потока, где требуется транслировать C++ CE в Win32 SE).

И второе. Eсли надо re-throw Win32 SE в C++ CE внутри __try{} блока, то надо изменять фильтр __except(filter) на EXCEPTION_CONTINUE_SEARCH.
Иначе будет выполняться блок __except(EXCEPTION_EXECUTE_HANDLER).

Например,

#ifdefSEH
#define TRY_SEHE { CSEH _seh_; inte_filter= EXCEPTION_EXECUTE_HANDLER; __try {
#define ON_CATCH_SEHE(_expressions) }_except(_seh= CSEH(GetExceptionCode(),GetExceptionInformation()),e_filter \
{ _expressions; } }
#define ON_CATCH_SEHE_THROW }_except(_seh= CSEH(GetExceptionCode(),GetExceptionInformation()),e_filter \
{ MYSQLEXCEPTIONseh; } }
#define MYSQLEXCEPTION_FILTER(var, _filter) {_e_filter_=_filter; MYSQLEXCEPTION((var));};
#define SET_EXCEPTION_FILTER(_filter) _e_filter_=_filter;
#else
#define TRY_SEHE ((void)0);
#define ON_CATCH_SEHE_THROW ((void)0);
#define MYSQLEXCEPTION_FILTER(var, _filter) MYSQLEXCEPTION((var));
#define SET_EXCEPTION_FILTER(_filter) ((void)0);
#endif

#ifdefINCLUDE_SOURCE_INFO
#define MYSQLEXCEPTION(var) throw CMySqlException((var)_FILE__,__FUNCTION__,__LINE_
#else
#define MYSQLEXCEPTION(var) throw CMySqlException((var))
#endif

class CMySqlConnection
{
...
public:
...
...
void Connect(const std::string &host, const std::string &username, const std::string &pwd,
const std::string &db, const unsigned int port = 0, unsigned long clientflag = 0)
{
...
...

TRY_SEHE
_close();
m_handle = mysql_init(NULL);
if(m_handle == NULL)
{
SET_EXCEPTION_FILTER(EXCEPTION_CONTINUE_SEARCH);
throw std::bad_alloc("Failed creating a new MYSQL connection handle.");
}

if( NULL == mysql_real_connect(m_handle, m_host.c_str(), m_username.c_str(), m_pwd.c_str(), m_db.c_str(), m_port, NULL, m_clientflag))
MYSQLEXCEPTION_FILTER(m_handle, EXCEPTION_CONTINUE_SEARCH);

ON_CATCH_SEHE_THROW
}
...
...
};
:) 06.05.07 11:44   [DamNet [Bugtraq.ru Team], tatar_0x4e, Ustin, HandleX]
Автор: Евгений Статус: Незарегистрированный пользователь
<"чистая" ссылка>
Честно говоря, у меня тоже героические попытки void'a развести народ на помощь в глубоких кишках VC++ вызывают сочувствующую улыбку... Только этим и могу ему помочь — не сдавайся! Я ща вообще на смоллтоке пишу! -)))) 07.05.07 08:48  
Автор: HandleX <Александр М.> Статус: The Elderman
<"чистая" ссылка>
Я просмотрел форумы MSDN. Меня смутило, что народ,... 08.05.07 04:06  
Автор: void <Grebnev Valery> Статус: Elderman
Отредактировано 08.05.07 04:21  Количество правок: 1
<"чистая" ссылка>
Я просмотрел форумы MSDN. Меня смутило, что народ, причисляющий себя чутли не к разработчикам в Microsoft, зачастую имеет противоположные точки зрения.
Одни говорят, мол, очень плохая идея компилировать с /EHa (никто не обьясняет, почему плохая идея, наверное, ссылка на статью MSDN, где только вскользь сказано овозможныховерхедах - по дефолту в голове). Другие окологуру (kenguru?) говорят, мол компилируй только с /EHa.

Наиболее здравый взгляд, мне кажется, у Рихтера. Он пишет, что сам он предпочитает вылавливать Win32 SE в __try/__except если надо, a затем транслировать SE в CE C++ _set_se_translator ...

Мне кажется что в VC 6.0 это не актуально ... Нет ... вроде актуально.
Я в общем не понял вопроса, но в exception-ах разбираюсь неплохо 08.05.07 11:55  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
Разве что ни фига не понимаю чем отличаются /EHs от /EHa (но я предпочитаю синхронный вариант - /EHs)

> Я просмотрел форумы MSDN. Меня смутило, что народ,
> причисляющий себя чутли не к разработчикам в Microsoft,
> зачастую имеет противоположные точки зрения.
> Одни говорят, мол, очень плохая идея компилировать с /EHa
> (никто не обьясняет, почему плохая идея, наверное, ссылка
> на статью MSDN, где только вскользь сказано овозможных
> оверхедах - по дефолту в голове). Другие окологуру


Оверхед на x86 платформе: пара десятков байт на стеке и прилинковывание нового фрейма к списку обработчиков в fs:0 плюс еще постоянный апдейт номера состояния при появлении новых локальных переменных (которые надо будет деструктить в случае раскрутки стека). А если еще учесть, что независимо от количество CE-шных try блоков в фукнции компилятор генерит только один SE-шный __try блок, то оверхэд может быть и отрицательным. Короче, практически нет оверхеда при отсутствии собственно самих ислкючительных ситуаций. Но вот если исключение таки бросается, то производится туева хуча работы, причем большая часть работы не зависит от того используется ли SE или CE (CE - это просто надстройка над SE). Но ситуации на то и исключительные, что не должны появляться часто. Поэтому их эффективность в удобстве доставки информации от места где произошло исключение к месту, где оно может быть обработано, а не в миллионах эксепшенов в секунду. По этому показателю CE однозначно лучше.

> (kenguru?) говорят, мол компилируй только с /EHa.
Компилируй с /EH :-)

> Наиболее здравый взгляд, мне кажется, у Рихтера. Он пишет,
> что сам он предпочитает вылавливать Win32 SE в
> __try/__except если надо, a затем транслировать SE в CE C++
> _set_se_translator ...

Чего то не того. __CxxFrameHandler проверяет по сигнатурам является ли exception C++сным и если нет, то вызывает se_translator (если он был установлен). А этот самый __CxxFrameHandler устанавливается хэндлером для try-catch блоков и генерится автоматом. В принципе, если ты отловил в __except исключение, которое брошено через throw, то в принципе нет нормального способа превратить его обратно в CE. Ловить надо в try-catch, а установленный se_translator (который при необходимости будет вызван обработчиком фрейма) должен перебросить SE в виде CE (вот здесь двойной оверхэд и по памяти и по времени обработки).

> Мне кажется что в VC 6.0 это не актуально ... Нет ...
> вроде актуально.

Актуально. EH практически не менялся со времен как минимум NT4.0 (скорее всего даже еще раньше).
[C++] Я в общем не понял вопроса, но в exception-ах разбираюсь неплохо 09.05.07 06:09  
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
Спасибо за ответ.

>Я в общем не понял вопроса,...
>> (kenguru?) говорят, мол компилируй только с /EHa.
>Компилируй с /EH :-)

VC++ 8.0, kомпилирую с /ЕHs (по дефолту):

try { int *i = 0; *i = 1; }
catch(...) { std::cout << "we will never be here."; }

Считай, что здесь, в try:
void third_party_api_I_have_to_use(void)
{
int *i = 0;
*i = 1;
}

Даже не надейся использовать здесь (с /ЕHs) _set_se_translator(). В VC++ 8.0 (не в VC++ 6.0) это не работает.
Получишь warning C4535: calling _set_se_translator() requires /EHa.
Даже хуже. Всё скомпилируется и рухнет при выполнении.
Здесь как минимум два варианта (на самом деле 3): компилировать с /ЕHa
или помещать third_party_api_I_have_to_use в __try/__except.


>>Чего то не того. __CxxFrameHandler проверяет по сигнатурам является ли >>exception C++сным и если нет, то вызывает se_translator (если он был установлен).

Ты не сможешь установить _set_se_translator( _My_translator_SE2CE) при компиляции с /ЕHs. Только с /ЕHа.


>>А этот самый __CxxFrameHandler устанавливается хэндлером для try-catch блоков >>и генерится автоматом.

Я ответил. Не генерится автоматом для /ЕHs.


>>В принципе, если ты отловил в __except исключение, которое брошено через >>throw, то в принципе нет нормального способа превратить его обратно в CE.

1) B __except я не ловлю исключений, брошенных через throw. Там я ловлю Win32 SE.
Другое дело, что любое исключение, в том числе и программное (throw) будет попадать в __except, если не правильно уцтановить фильтр __except.

Например, такой код не будет работать:
void foo(void)
{
int i = 0;
__try
{
bool something_wrong = true;
if (something_wrong)
throw 1;

}
__except(1)
{
//we will always be here and never in the outside catch()
i = 1;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int i = 0;
try
{
foo();
}
catch(...)
{
//we will anever be here :(
int i = 1;
}

return 0;
}


Такой код будет работать корректно:
void foo(void)
{
int i = 0;
int filter = 1;
__try
{
bool something_wrong = true;
if (something_wrong)
{
filter = 0;
throw 1;
}

}
__except(filter)
{
// OK. We will never be here and we will be in the outside catch()
i = 1;
}
}
int _tmain(int argc, _TCHAR* argv[])
{

int i = 0;
try
{
foo();
}
catch(...)
{
//OK
//we are overhere
int i = 1;
}
return 0;
}


2) Из __except ты можешь нормально и легально throw C++ CE.


>>Ловить надо в try-catch, а установленный se_translator (который при >>необходимости будет вызван обработчиком фрейма) должен перебросить SE в виде >>CE (вот здесь двойной оверхэд и по памяти и по времени обработки).

Об этом и речь. Но только вначале надо транслировать SE 2 C++.
Ага. Почитал MSDN. Там явно указано, что se_translator можно... 10.05.07 14:33  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> Даже не надейся использовать здесь (с /ЕHs)
> _set_se_translator(). В VC++ 8.0 (не в VC++ 6.0) это не
> работает.
> Получишь warning C4535: calling _set_se_translator()
> requires /EHa.

Ага. Почитал MSDN. Там явно указано, что se_translator можно ставить ТОЛЬКО при /EHa

> Здесь как минимум два варианта (на самом деле 3):
> компилировать с /ЕHa

/EHa отличается от /EHs только тем, что экспепшн ожидается в любой инструкции, а не только при вызовах функций. Следовательно в общем случае чуть чаще апдейтится состояние (например, если между двумя вызовами функций сконструировано два объекта, то при /EHs это будет одно состояние и при транзишене из него во время анвинда деструктятся оба, в случае же /EHa это будет два состояния: при анвинде сначала из во втором состоянии вызовется деструктор второго объекта и будет переход в первое). Оверхед очень маленький.

> или помещать third_party_api_I_have_to_use в
> __try/__except.

На мой взгляд лучше транслятор и /EHa, но если архитектура позволяет то можно и так

> Ты не сможешь установить _set_se_translator(
> _My_translator_SE2CE) при компиляции с /ЕHs. Только с /ЕHа.

Ага, я уже понял. Я имел в виду С++-сные исключения вообще без деления на синхронныи и асинхронные

> Я ответил. Не генерится автоматом для /ЕHs.

Ну вообще то генерится, просто там с состояниями для раскрутки проблема. Сам же анвинд и весь обслуживающий код одинаковый для обоих типов эксепшенов (можешь скомпилировать с /FAcs и убедиться самостоятельно).

Все что выше - поскипал, ибо никаких возражений нет.

> Такой код будет работать корректно:
> void foo(void)
> {
> int i = 0;
> int filter = 1;
> __try
> {
> bool something_wrong = true;
> if (something_wrong)
> {
> filter = 0;
> throw 1;
> }
>
> }
> __except(filter)
> {
> // OK. We will never be here and we will be
> in the outside catch()
> i = 1;
> }
> }
> int _tmain(int argc, _TCHAR* argv[])
> {
>
> int i = 0;
> try
> {
> foo();
> }
> catch(...)
> {
> //OK
> //we are overhere
> int i = 1;
> }
> return 0;
> }
>

Лушче не так.
C++ эксепшены имеют две особенности:
ExceptionRecord->ExceptionCode == 0xe06d7363
и
ExceptionRecord->ExceptionInformation[0] == 0x19930520

Хотя второе необязательно. В обработчике встречал сравнение с 0x19930521 и 0x19930522, но вживую таких исключений никогда не видел. С другой стороны, хорошее регресс тестирование (и правильно расставленные assert-ы) не даст таким исключениям появиться неожиданно.

В общем если тебе не по душе /EHa и ты хочешь в __try-__except-е пропустить C++сные исключения просто делай в фильтре GetExceptionInformation и сравнивай оба magic числа или вообще так:

__try {
    throw 0;
} __except (GetExceptionCode() == 0xe06d7363 ? EXCEPTION_CONTINUE_SEARCH : EXCEPTION_EXECUTE_HANDLER) {
// we will never reach here
}

---
[C++] Ага. Почитал MSDN. Там явно указано, что se_translator можно... 13.05.07 08:09  
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
> Лушче не так.
> C++ эксепшены имеют две особенности:
> ExceptionRecord->ExceptionCode == 0xe06d7363
> и
> ExceptionRecord->ExceptionInformation[0] == 0x19930520
>
> Хотя второе необязательно. В обработчике встречал сравнение
> с 0x19930521 и 0x19930522, но вживую таких исключений
> никогда не видел. С другой стороны, хорошее регресс
> тестирование (и правильно расставленные assert-ы) не даст
> таким исключениям появиться неожиданно.
>
> В общем если тебе не по душе /EHa и ты хочешь в
> __try-__except-е пропустить C++сные исключения просто делай
> в фильтре GetExceptionInformation и сравнивай оба magic
> числа или вообще так:
>
>
> __try {
>     throw 0;
> } __except (GetExceptionCode() == 0xe06d7363 ?
> EXCEPTION_CONTINUE_SEARCH : EXCEPTION_EXECUTE_HANDLER) {
> // we will never reach here
> }

---

Ты прав. Так лучше. Я добавил в код обработку GetExceptionCode() == 0xe06d7363.
Получилсь компактнее, чище и понятнее. И это главное.

Интересно, что 0xe06d7363 это

"...The code is actually a cryptic mnemonic device, with the initial "E" standing for "exception" and the final 3 bytes (0x6D7363) representing the ASCII values of "msc". ", ;) (http://support.microsoft.com/kb/185294). Как они себя любят, "Emsc" :)

По поводу же "... В обработчике встречал сравнение с 0x19930521 и 0x19930522 ... " - то я пока воздержался добавлять в код.
Похоже это информация о версии комилятора, http://www.openrce.org/articles/full_view/21.

Еще раз спасибо за постепенную ликвидацию моей неграмотности ;)
[C++] Сухой остаток 11.05.07 05:37  
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
... я бы подвёл такую черту. Согласен с твоими замечниями.
И, конечно, спасибо за твои дополнительные исследования вопроса.
Для меня это важно, в скором времени придётся обсуждать вопрос на работе.
В принципе осталось только пара коментариев:

>>На мой взгляд лучше транслятор и /EHa
1) Я тоже так считаю.
Даже в худшей ситуации поймаешь исключение в cath(...).
Там тоже, правда, не так всё розово и гарантировано. Например, если исключение возникает в твоём потоке в котором вызываются функции неких библиотек из 3party-DLL, то нет гарантии что будет вывана именно твоя функция-транслятор, а не транслятор переустановленый в этой DLL. Хорошо если "их" транслятор будет транслировать исключение в исключение класса class CTheirException : public std::exception (...). Тогда есть шанс, например, выдать в лог сообщение e.what()

try
{
...
}
catch(std::exception& & e)
{
Log(e.what());
}

Иначе только catch(...), что, конечно, лучше чем ничего.

2) В этой ситуации поможет сочетание /EHa с непосредсвенным включением сомнительного кода в __try{}__except{}.

3) Остаётся вопросом, почему размер release кода уменьшается на 40%, если при компиляции с /EHa дополнительно непосредственно использовать __try{}__except{} в некоторых участках кода, по сравнению с компиляцией /EHa но без __try{}__except{}.

>>/EHa отличается от /EHs только тем, что экспепшн ожидается в любой инструкции,
>>а не только при вызовах функций. Следовательно в общем случае чуть чаще
>>апдейтится состояние (например, если между двумя вызовами функций
>>сконструировано два объекта, то при /EHs это будет одно состояние и при
>>транзишене из него во время анвинда деструктятся оба, в случае же /EHa это
>>будет два состояния: при анвинде сначала из во втором состоянии вызовется
>>деструктор второго объекта и будет переход в первое). Оверхед очень маленький.

Я бы ещё добавил, что при /EHs не гарантируется (при неправильной обработке в __try/__except) вызов деструкторов как экземпляров классов, так и деструкторов мембер-переменных этого класса при раскрутке. Ничего такого не происходит при /EHа. Все деструкторы вызываются. И это огромный плюс в надёжности кода при комиляции с /EHа.

Thx.
1






Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2021 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach