Что перехватывать?
От: licedey  
Дата: 09.11.11 10:14
Оценка:
Нужно предусмотреть любое развитие событий в каждой функции, при этом диагностику выводить информативно. Приложение мультипоточно. Какой вариант посоветуете?
Реализовать в виде макроса было бы удобно. Что-то вроде

FX_TRY
... // тут кончается память, место на диске, шнур из розетки вылетает итд.
FX_CATCH
Log( /* тут выводить подробную инфу, откуда? */ )
FX_FINALLY
... // освобождаем ресурсы


По собственному опыту, как бы эти макросы реализовать лучше?
Re: Что перехватывать?
От: zaufi Земля  
Дата: 09.11.11 12:37
Оценка:
Здравствуйте, licedey, Вы писали:

L>По собственному опыту, как бы эти макросы реализовать лучше?


по собственному опыту лучше с макросами не связываться насколько это возможно. а в данном случае это вполне возможно:

void handle_exceptions() 
{
#if defined(__GNUC__) && GCC_VERSION > 40100
  assert("No need to call this function w/o active exception" && 0 != abi::__cxa_current_exception_type());
#endif
  try 
  {
    throw;
  }
  catch (const std::runtime_error& e) {
    // handle it!
  }
  //
  // ... catch any other concrete exception types here...
  //
  catch (const std::exception& e) {
    // handle it!
  }
}

void some_function()
{
  try
  {
    // do smth what may throw exceptions...
  }
  catch (...)
  {
    handle_exceptions();
  }
}
void another_function()
{
  try
  {
    // do some other stuff what may throw exceptions...
  }
  catch (...)
  {
    handle_exceptions();
  }
}
Re[2]: Что перехватывать?
От: licedey  
Дата: 09.11.11 12:58
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>Здравствуйте, licedey, Вы писали:


L>>По собственному опыту, как бы эти макросы реализовать лучше?


Z>по собственному опыту лучше с макросами не связываться насколько это возможно. а в данном случае это вполне возможно:


Z>
Z>void handle_exceptions() 
Z>{
Z>#if defined(__GNUC__) && GCC_VERSION > 40100
Z>  assert("No need to call this function w/o active exception" && 0 != abi::__cxa_current_exception_type());
Z>#endif
Z>  try 
Z>  {
Z>    throw;
Z>  }
Z>  catch (const std::runtime_error& e) {
Z>    // handle it!
Z>  }
Z>  //
Z>  // ... catch any other concrete exception types here...
Z>  //
Z>  catch (const std::exception& e) {
Z>    // handle it!
Z>  }
Z>}

Z>void some_function()
Z>{
Z>  try
Z>  {
Z>    // do smth what may throw exceptions...
Z>  }
Z>  catch (...)
Z>  {
Z>    handle_exceptions();
Z>  }
Z>}
Z>void another_function()
Z>{
Z>  try
Z>  {
Z>    // do some other stuff what may throw exceptions...
Z>  }
Z>  catch (...)
Z>  {
Z>    handle_exceptions();
Z>  }
Z>}
Z>


Насколько я понял из кода, handle_exceptions — хватает все возможное? В том числе например, деление на 0, обращение к NULL или к уже освобожденной памяти? Можете ткнуть где все возможные exception'ы перечислены, под MSVS в частности. И WinApi обработка исключений, тоже интересует. Заранее благодарен.
Re[3]: Что перехватывать?
От: Кодт Россия  
Дата: 09.11.11 15:28
Оценка:
Здравствуйте, licedey, Вы писали:

L>Насколько я понял из кода, handle_exceptions — хватает все возможное? В том числе например, деление на 0, обращение к NULL или к уже освобожденной памяти? Можете ткнуть где все возможные exception'ы перечислены, под MSVS в частности. И WinApi обработка исключений, тоже интересует. Заранее благодарен.


Стало быть, платформа — винды, и речь идёт о красивой обработке SEH'ов?
http://msdn.microsoft.com/en-us/library/ms680657(v=VS.85).aspx

А предполагается ли смешивать обработку C++ных и структурных исключений?

Можно попробовать транслировать SEH в C++ (хотя бы на уровень catch(...), как исключение неопознанного типа — компилятор такое умеет) и в обработчике смотреть, не SEH ли это, и если да, то какой именно.
А можно сразу __try-__except.
И смотреть на код исключения (GetExceptionCode).
Перекуём баги на фичи!
Re: Что перехватывать?
От: avbochagov Россия  
Дата: 10.11.11 05:53
Оценка:
Здравствуйте, licedey, Вы писали:

l> Нужно предусмотреть любое развитие событий в каждой функции, при этом диагностику выводить информативно. Приложение мультипоточно. Какой вариант посоветуете?

l> Реализовать в виде макроса было бы удобно. Что-то вроде

l> FX_TRY

l> ... // тут кончается память, место на диске, шнур из розетки вылетает итд.
l> FX_CATCH
l> Log( /* тут выводить подробную инфу, откуда? */ )
l> FX_FINALLY
l> ... // освобождаем ресурсы

l> По собственному опыту, как бы эти макросы реализовать лучше?


мне кажется, что вы немного неверно сформулировали задачу.

Написать приложение, которое корректно работает с исключениями -- это достаточно сложная задача, требующая тщательного планирования и большого опыта. Почитать об этом можно у таких грандов как Саттер, Александреску и др.
К тому же вы планируете использовать аппаратные исключения кидаемые из ядра Windows.
Тернистая дорожка получается...

Может попробовать зайти с другой стороны: спроектировать и написать приложение таким образом, чтобы всевозможные отказы не были исключительной ситуацией, а были заранее предусмотрены?
Тогда никаких особенных требований не будет ни к обработке исключений, ни к логированию.
avalon 1.0rc3 rev 416, zlib 1.2.3
Re[2]: Что перехватывать?
От: licedey  
Дата: 11.11.11 00:56
Оценка:
Здравствуйте, avbochagov, Вы писали:

A>Здравствуйте, licedey, Вы писали:


l>> Нужно предусмотреть любое развитие событий в каждой функции, при этом диагностику выводить информативно. Приложение мультипоточно. Какой вариант посоветуете?

l>> Реализовать в виде макроса было бы удобно. Что-то вроде

l>> FX_TRY

l>> ... // тут кончается память, место на диске, шнур из розетки вылетает итд.
l>> FX_CATCH
l>> Log( /* тут выводить подробную инфу, откуда? */ )
l>> FX_FINALLY
l>> ... // освобождаем ресурсы

l>> По собственному опыту, как бы эти макросы реализовать лучше?


A>мне кажется, что вы немного неверно сформулировали задачу.


A>Написать приложение, которое корректно работает с исключениями -- это достаточно сложная задача, требующая тщательного планирования и большого опыта. Почитать об этом можно у таких грандов как Саттер, Александреску и др.

A>К тому же вы планируете использовать аппаратные исключения кидаемые из ядра Windows.
A>Тернистая дорожка получается...

A>Может попробовать зайти с другой стороны: спроектировать и написать приложение таким образом, чтобы всевозможные отказы не были исключительной ситуацией, а были заранее предусмотрены?

A>Тогда никаких особенных требований не будет ни к обработке исключений, ни к логированию.

Я уточню. Мой проект — это антивирусный сканер, DLL с несколькими функциями, к которым могут обращаться несколько разных consumer'ов (процессов, других DLL). Каждая функция запускает свой поток с задачей. Например ScanFolder или ScanCookies. Все пишется на MS C++/WinAPI/STL. Моя задача, чтобы при любых раскладах consumer не завис при "падении" одной задачи. Проверять коды возврата WinApi и диагностировать GetLastError() я так понимаю будет достаточно. Но есть еще С++ исключения.

Как посоветуете быть. Наиболее простым будет, обернуть проверка коды возврата WinApi-функций и генерировать свой WinApiException например. Тела топовых-функций облачить в try/catch и как в ответе Кодт'a, обрабатывать стандартные С++ exceptions+WinApiException. Что посоветуете? Вариант с "Предусмотреть все" не получится, хотя бы потому что вызывающий код мне неизвестен.

Еще вопрос. Можно ли перехватывать технические исключения в MSVS C++? Допущенные по невнимательности. Как, переполнение стека, обращение за пределы адресного пространства? Часто бывает вылет — memory access on adresss 0xxx corrupted.

Спасибо.
Re[3]: Что перехватывать?
От: Centaur Россия  
Дата: 11.11.11 05:07
Оценка:
Здравствуйте, licedey, Вы писали:

L>Еще вопрос. Можно ли перехватывать технические исключения в MSVS C++? Допущенные по невнимательности. Как, переполнение стека, обращение за пределы адресного пространства? Часто бывает вылет — memory access on adresss 0xxx corrupted.


Баги в программе нужно фиксить, а не заметать под ковёр.
Re[3]: Что перехватывать?
От: avbochagov Россия  
Дата: 11.11.11 09:16
Оценка:
Здравствуйте, licedey, Вы писали:

l> Я уточню. Мой проект — это антивирусный сканер, DLL с несколькими функциями, к которым могут обращаться несколько разных consumer'ов (процессов, других DLL). Каждая функция запускает свой поток с задачей. Например ScanFolder или ScanCookies. Все пишется на MS C++/WinAPI/STL. Моя задача, чтобы при любых раскладах consumer не завис при "падении" одной задачи. Проверять коды возврата WinApi и диагностировать GetLastError() я так понимаю будет достаточно. Но есть еще С++ исключения.


Правильно ли я понял: Вы пишете DLL, которую дергают другие приложения за "выставленные" наружу функции. Так?

С++ исключения — это свойства языка. Получить исключение можно только если его кто-то явным образом создал с помощью throw.

l> Как посоветуете быть. Наиболее простым будет, обернуть проверка коды возврата WinApi-функций и генерировать свой WinApiException например. Тела топовых-функций облачить в try/catch и как в ответе Кодт'a, обрабатывать стандартные С++ exceptions+WinApiException. Что посоветуете?


Если я правильно понял как должна работать ваша DLL, то я посоветую ровно тоже самое что и Кодт. Только маленькое уточнение -- ваша DLL должна состоять из двух слоёв:
  1. Внешний интерфейс DLL — пишется на чистом С. Никаких исключений тут нет. Только коды возврата. Основная его задача провести все возможные проврки и передать аргументы (если они правильные) в следующий слой. Почему чистый С: это позволит использовать вашу библиотеку с минимальными усилиями на всем спектре языков программирования для Windows.
  2. А здесь уже Ваша основная логика, написанная на C++. Если хотите использовать исключения — то они никогда не должны отсюда уходить в первый слой.

l> Вариант с "Предусмотреть все" не получится, хотя бы потому что вызывающий код мне неизвестен.


А Вам и не надо "Предусмотреть все". Достаточно, чтобы Ваш код принимал только правильные параметры и корректно по ним отрабатывал. В случае некорретных параметров, или возникновения ошибки достаточно вернуть код ошибки, возможно с расширенным описанием для улучшения диагностики.

l> Еще вопрос. Можно ли перехватывать технические исключения в MSVS C++? Допущенные по невнимательности. Как, переполнение стека, обращение за пределы адресного пространства? Часто бывает вылет — memory access on adresss 0xxx corrupted.


А вот этого быть не должно никогда.
Такие ошибки должны быть пойманы на этапе тестирования.
У вас ведь есть план тестирования?

l> Спасибо.


P.S. что касается технических исключений, то достаточно подумать, что вы сможете сделать если разрушен стэк? и из этого строить политику по их использованию.
avalon 1.0rc3 rev 416, zlib 1.2.3
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.