
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.30] |
![]() |
|
Страницы: (3) 1 [2] 3 все ( Перейти к последнему сообщению ) |
Сообщ.
#16
,
|
|
|
Проверил с теми опциями котрые доступны в IDE. Исключения в Release версии ловятся только при полном отключении оптимизации.
|
Сообщ.
#17
,
|
|
|
Цитата У тебя z не используется, поэтому компилятор наверняка выкинул код её вычисления. Да правильно, а я не догадался. Но почему тогда не выкидывает при ![]() ![]() float x,y,z; x = 1.0; y = 0.0; z = x/y; |
Сообщ.
#18
,
|
|
|
Если добавить volatile, то всё работает - ловит исключение. но всё же странно почему компилятор вырезает блоки try-catch типа с целью оптимизации! |
![]() |
Сообщ.
#19
,
|
|
Та не блок он вырезал, а вычисление z. Кроме volatile от супероптимизации её вычисления его б остановило объявление z глобальной с внешним связыванием. Когда z локальная, её время жизни полностью под контролем оптимизатора, вот он и берёи на себя больше, чем в этом примере от него требуется.
Dem_max, не знаю. Пути оптимизатора неисповедимы. Наверно не рискнул из-за закулисной жизни _matherr(). |
Сообщ.
#20
,
|
|
|
Понятно, не врубился сразу. С глобальными тоже работает. Про деструкторы по ссылке пока ещё почитаю.
Qraizer вы как считаете использовать лучше try-catch и /EHa или же __try/__except для того чтобы надёжно ловить все исключения(от системы, не программные throw)? |
![]() |
Сообщ.
#21
,
|
|
По try/catch ты не получишь подробной информации о проблеме, если не воспользуешься какой-нибудь прослойкой в лице хотя бы той же _set_se_translator(). Если тебя не интересует эта информация, а интересует только безопасный код, не допускающий утечек ресурсов из-за проблем не в твоём коде, то это не проблема.
По __try/__except ты не получишь информации о C++-проблеме вообще никак, ибо кухня С++ exception handling вообще не стандартизирована и не документирована в отличие от SEH. Опять же это не проблема, если тебя интересует только безопасный код. Для безопасного кода достаточно RAII посредством пар "конструктор/деструктор" и ключика -EHa. Для получения информации о проблеме, если вдруг она-таки потребуется, для C++ достаточно класса для инкапсуляции SEH-контекста и _set_se_translator(). Для того же в случае C надёжного решения нет. Вывод: try/catch предпочтительнее. Однако в функциях, в чьих контексте нет объектов с нетривиальными деструкторами можно и __try/__except и/или __try/__finally, это будет чуть эффективнее. Но в случае появления в будущем в их констекте таких объектов придётся переписывать. |
Сообщ.
#22
,
|
|
|
Цитата Qraizer @ По try/except ты не получишь подробной информации о проблеме, если не воспользуешься какой-нибудь прослойкой в лице хотя бы той же _set_se_translator(). Может вы имели ввиду try/catch? Цитата Qraizer @ По __try/__except ты не получишь информации о C++-проблеме вообще никак, ибо кухня С++ exception handling вообще не стандартизирована и не документирована в отличие от SEH. А какие не мои собственные исключения С++(системные) могут привести к вылету из программы? Цитата Qraizer @ Для безопасного кода достаточно RAII посредством пар "конструктор/деструктор" и ключика -EHa. Будьте добры, что такое RAII? Цитата Qraizer @ Вывод: try/except предпочтительнее. Не понял здесь немного. Вы различаете __except и except? Я в MSDN нашёл информацию только об __except. Может вы имели ввиду try/catch? |
![]() |
Сообщ.
#23
,
|
|
Ну да, try/catch. Перекопипастил.
Поправил. Добавлено Цитата neokoder @ "Не твои собственные", в смысле "не в твоём коде". Свой код ты можешь вылизать в абсолют, хотя бы теоретически. Но когда ты вызываешь не свой код, находящийся в библиотеке не твоего авторства к примеру, с ним ты ничего не сможешь поделать. (Конечно, наличие исключений отнюдь не означает наличие багов, это ещё и может означать плохое тобою чтение документации.) А какие не мои собственные исключения С++(системные) могут привести к вылету из программы? Добавлено Цитата neokoder @ Resource Allocation Is Initialization. Идиома такая. Конструктор и только конструктор захватывает ресурс и объявляет экземпляр класса его владельцем. Деструктор и только деструктор его освобождает. Стандартом языка гарантируются вызовы деструкторов локальных объектов в любом случае, и при обычном завершении функции, и при размотке стека при исключении. Это позволяет резко сократить количество try-блоков в программе и при этом гарантировано не иметь утечек. Эта тема вот тут рассмотрена гораздо подробнее и с примерами. Будьте добры, что такое RAII? |
Сообщ.
#24
,
|
|
|
Для себя решил. Использовать __try, __finally,__leave как наилучший вариант обработки исключительных ситуаций в своём коде. Примером может служить код функции из книги Рихтера:
![]() ![]() DWORD Funcarama4() { // Внимание: инициализируйте все переменные, предполагая худшее HANDLE hFile = INVALID_HANDLE_VALUE; PVOID pvBuf = NULL; // предполагаем, что выполнение функции будет неудачным BOOL bFunctionOk = FALSE; __try { DWORD dwNumBytesRead; BOOL bOk; hFile = CreateFile(TEXT("SOHEDATA.DAT"), GENERIC_READ,FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { __leave; } pvBuf = VirtualAlloc(NULL,1024, MEM_COMMIT, PAGE_READWRITE); if (pvBuf == NULL) { __leave; } bOk = ReadFile(hFile, pvBuf, 1024, &dwNumBytesRead, NULL); if (!bOk || (dwNumBytesRead == 0)) { __leave; } // что-то делаем с данными //... // функция выполнена успешно bFunctionOk = TRUE; } __finally { // очистка всех ресурсов if (pvBuf != NULL) VirtualFree(pvBuf,1024,MEM_RELEASE|MEM_DECOMMIT); if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); } // продолжаем что-то делать return(bFunctionOk); } Что касается вызова сторонних функций из библиотек, то для них буду использовать следующий принцип. Программу буду компилировать по умолчанию с ключом (/EHsc) или (/EHs) (в зависимости от задачи). Т.е я не буду ловить структурные исключения c помощью catch. Просто нет желания связываться с _set_se_translator, который необходимо определять для каждого потока, кроме того, если вызывается функция из dll, то она может создавать свой поток и я уже никак не смогу перехватить исключение в этом потоке. Если я не прав поправьте. Поэтому я решил просто использовать 2 функции для вызова стороннего кода- одну для обработки С++ исключений, а вторую для структурных. Т.е. выглядет это так: ![]() ![]() //compile with (/EHsc) int x,y,z; void SafeCall_1(); LONG ExceptFilter (DWORD except_code) { if (except_code==EXCEPTION_INT_DIVIDE_BY_ZERO) { //здесь мы узнаём о произошедшем исключении printf("EXCEPTION_INT_DIVIDE_BY_ZERO\n"); return EXCEPTION_EXECUTE_HANDLER; } else { //здесь мы не обрабатываем те исключения которые система должна решить сама printf("Uknown exception\n"); return EXCEPTION_CONTINUE_SEARCH; } } void UnknownFunction(int what) { x = 1; y = 0; z = x/y; if (what==1) throw (char *)"I am throw an exception"; } void SafeCall() { __try { SafeCall_1(); } __except(ExceptFilter(GetExceptionCode())) { } printf("We don't exit and can continue work\n"); } void SafeCall_1() { try { UnknownFunction(2); } catch(char *mes) { //здесь мы узнаём о произошедшем исключении printf("Unknown function has raised an exception with message: %s\n",mes); } catch(...) { //здесь мы узнаём о произошедшем исключении printf("Unknown function has raised an unknown exception\n"); } } int _tmain(int argc, _TCHAR* argv[]) { SafeCall(); printf("Press any key to close the window..."); _getch(); return 0; } Был бы рад услышать ваши отклики и замечания. Особенно в плане того какие струтурные исключения нельзя ловить, а надо дать системе обработать их самой(т.е. это не означает вылета из программы). Вообще есть такие? |
![]() |
Сообщ.
#25
,
|
|
neokoder, пример Рихтера попадает под упомянутое мною исключение. Она сугубо Сшная, так что Плюсовым try там делать нечего.
Цитата neokoder @ Ну и правильно. Сам так делаю. Это иногда требует некоторой дополнительной ручной работы, но это оправдано. В Плюсовом коде SEH исключений либо нет, т.к. их вычищают, ибо это ошибки, их проще предотвратить проверкой параметров, чем сглаживать последствия от них, либо документированы, а значит не неожиданны, и легко хедлятся индивидуально по месту ещё на стадии программирования. Бывают, конечно, неприятности с багами в библиотеках, но для этого существуют багрепорты их авторам и временные их воркароунды в своём коде. Да и редки они обычно, если библиотека не левый какой-нибудь "компонент". А если нередки, то написать самому обычно дешевле выходит, хотя бы в плане нервов. Что касается вызова сторонних функций из библиотек, то для них буду использовать следующий принцип. ... Добавлено Цитата neokoder @ Эти потоки тебя вообще-то и не касаются. Они вряд ли будут выполнять твой код. А если будут, то и проблемы уже нет, перехватывай. если вызывается функция из dll, то она может создавать свой поток и я уже никак не смогу перехватить исключение в этом потоке Добавлено Цитата neokoder @ Классика. Не надо обрабатывать исключение, если ты не знаешь, что с ним делать. Отправляй дальше, там найдётся кому обработать. Всё, что тебе тут надо - откатиться к своим инвариантам. RAII тут как нельзя кстати - 0 строк кода за исключением кода деструкторов. Ну, или __finally, если это C. Посмотри по той ссылке пример с реализацией SS::operator=(). какие струтурные исключения нельзя ловить, а надо дать системе обработать их самой(т.е. это не означает вылета из программы). |
Сообщ.
#26
,
|
|
|
Цитата Qraizer @ neokoder, пример Рихтера попадает под упомянутое мнорю исключение. Она сугубо Сшная, так что Плюсовым try там делать нечего. Да, а я в принципе С++ функциями редко пользуюсь, разве что классы свои делаю. А для работы с С++ функциями, которые могут дать исключения тот же new я всегда буду заключать в блоки try...catch. Добавлено Цитата Qraizer @ Эти потоки тебя вообще-то и не касаются. Они вряд ли будут выполнять твой код. А если будут, то и проблемы уже нет, перехватывай. Нет, ну как не касаются. Я вызвал функцию из сторонней dll , она создала поток, в потоке произошло исключение которое она не смогла обработать. Всё! Если я пользуюсь _set_se_translator перехватить это исключение я уже не смогу и программа завершится. Вот почему я не желаю пользоваться _set_se_translator. А с помощью 2-х функций такое исключение всегда поймается. Если не прав поправьте. Добавлено Цитата Qraizer @ Идиома такая. Конструктор и только конструктор захватывает ресурс и объявляет экземпляр класса его владельцем. Деструктор и только деструктор его освобождает. Стандартом языка гарантируются вызовы деструкторов локальных объектов в любом случае, и при обычном завершении функции, и при размотке стека при исключении. Ну если честно, ничего не зная о RAII я так всегда и делал ![]() 1) Будет ли гарантированно раскручиваться стек и вызываться деструкторы локальных объектов(классов в основном) после возникновения структурного(SEH) исключения? 2) Если да, то обязательно ли для этого использовать ключ компилятора (/EHa) или можно обойтись(/EHsc)? |
Сообщ.
#27
,
|
|
|
Цитата Qraizer @ Классика. Не надо обрабатывать исключение, если ты не знаешь, что с ним делать. Отправляй дальше, там найдётся кому обработать. Так вот здесь конкретный вопрос. Какие исключения именно для моего кода(не стороннего) из нижеследующего списка мне необходимо принять с EXCEPTION_EXECUTE_HANDLER, и просто ничего не делать, главное чтобы программа продолжала работу, например случайное EXCEPTION_INT_DIVIDE_BY_ZERO, а какие исключения надо отдать системе с помощью EXCEPTION_CONTINUE_SEARCH, но при этом главное чтобы по возможности программа не завершилась, в крайнем случае только тогда, когда исключение ведёт к серьёзному нарушению в программе и её продолжение чревато последствиями. Пусть уж в этом случае создаёт минидамп и отправляет его Microsoft как обычно. ![]() ![]() #define EXCEPTION_ACCESS_VIOLATION STATUS_ACCESS_VIOLATION #define EXCEPTION_DATATYPE_MISALIGNMENT STATUS_DATATYPE_MISALIGNMENT #define EXCEPTION_BREAKPOINT STATUS_BREAKPOINT #define EXCEPTION_SINGLE_STEP STATUS_SINGLE_STEP #define EXCEPTION_ARRAY_BOUNDS_EXCEEDED STATUS_ARRAY_BOUNDS_EXCEEDED #define EXCEPTION_FLT_DENORMAL_OPERAND STATUS_FLOAT_DENORMAL_OPERAND #define EXCEPTION_FLT_DIVIDE_BY_ZERO STATUS_FLOAT_DIVIDE_BY_ZERO #define EXCEPTION_FLT_INEXACT_RESULT STATUS_FLOAT_INEXACT_RESULT #define EXCEPTION_FLT_INVALID_OPERATION STATUS_FLOAT_INVALID_OPERATION #define EXCEPTION_FLT_OVERFLOW STATUS_FLOAT_OVERFLOW #define EXCEPTION_FLT_STACK_CHECK STATUS_FLOAT_STACK_CHECK #define EXCEPTION_FLT_UNDERFLOW STATUS_FLOAT_UNDERFLOW #define EXCEPTION_INT_DIVIDE_BY_ZERO STATUS_INTEGER_DIVIDE_BY_ZERO #define EXCEPTION_INT_OVERFLOW STATUS_INTEGER_OVERFLOW #define EXCEPTION_PRIV_INSTRUCTION STATUS_PRIVILEGED_INSTRUCTION #define EXCEPTION_IN_PAGE_ERROR STATUS_IN_PAGE_ERROR #define EXCEPTION_ILLEGAL_INSTRUCTION STATUS_ILLEGAL_INSTRUCTION #define EXCEPTION_NONCONTINUABLE_EXCEPTION STATUS_NONCONTINUABLE_EXCEPTION #define EXCEPTION_STACK_OVERFLOW STATUS_STACK_OVERFLOW #define EXCEPTION_INVALID_DISPOSITION STATUS_INVALID_DISPOSITION #define EXCEPTION_GUARD_PAGE STATUS_GUARD_PAGE_VIOLATION #define EXCEPTION_INVALID_HANDLE STATUS_INVALID_HANDLE #define EXCEPTION_POSSIBLE_DEADLOCK STATUS_POSSIBLE_DEADLOCK |
Сообщ.
#28
,
|
|
|
Цитата neokoder @ Для себя решил. Использовать __try, __finally,__leave как наилучший вариант обработки исключительных ситуаций в своём коде. Примером может служить код функции из книги Рихтера: А по моему это уже перебор. т.е. этот пример демонстрирует приём работы с __try, __leave, __finally но по сути здесь нет исключений. Гораздо удобнее использовать классы-обьекты содержащие CreateFile, VirtualAlloc, ReadFile и.т.п. и высвобождающие ресурсы в деструкторе. В том случае, если это не удобно делать соотв. методом. |
Сообщ.
#29
,
|
|
|
Цитата ЫукпШ @ А по моему это уже перебор. т.е. этот пример демонстрирует приём работы с __try, __leave, __finally но по сути здесь нет исключений. Ну естественно исключений нет, но появится могут в "любой момент" ![]() Цитата ЫукпШ @ Гораздо удобнее использовать классы-обьекты содержащие CreateFile, VirtualAlloc, ReadFile и.т.п. и высвобождающие ресурсы в деструкторе. В том случае, если это не удобно делать соотв. методом. Ну а вообще, кому что удобнее. ЫукпШ, вы по более важным(для меня) вопросам в моих последних 2-х постах можете что-то сказать? |
Сообщ.
#30
,
|
|
|
Цитата neokoder @ ЫукпШ, вы по более важным(для меня) вопросам в моих последних 2-х постах можете что-то сказать? А я то как раз и ответил на самый важный, на мой взгляд, вопрос. В вышеупомянутом примере имеет место явная попытка скрестить ужа с ежом. Что не нужно. Пусть высвобождением ресурсов занимаются обьекты, а блоки try/canth ловят и обрабатывают исключения. Одно другому не мешает. Добавлено Цитата neokoder @ 1) Будет ли гарантированно раскручиваться стек и вызываться деструкторы локальных объектов(классов в основном) после Да, и информацию об этом легко найти в Сети. тут, например И в книгах, конечно. Добавлено Цитата neokoder @ Так вот здесь конкретный вопрос. Какие исключения именно для моего кода(не стороннего) из нижеследующего списка мне необходимо принять с EXCEPTION_EXECUTE_HANDLER, и просто ничего не делать, главное чтобы программа продолжала работу, например случайное EXCEPTION_INT_DIVIDE_BY_ZERO, а какие исключения надо отдать системе с помощью EXCEPTION_CONTINUE_SEARCH, Об этом может знать только автор конкретной программы - как она должна вести себя в этих случаях. Что касается "отдавать системе", то система завершит аппликэйшын стандартным мессэдж-боксом. На мой взгляд, в необходимом случае лучше показать свой собственный. |