Нельзя ли приучить программу реагировать на чтение за пределами памяти или по нулевому адресу, с помощью try catch? Тот самый try в виндовсе спасает практически от любых проблем, в то время как в linux не реагирует ни на что кроме исключений вызваных в ручную.
Приучить его тоже не очень получается:
void hand(int sig)
{
printf("signal: %d\n",sig);
throw;
}int main()
{
struct sigaction act;
memset(&act,0,sizeof(act));
act.sa_handler=hand;
sigaction(SIGSEGV,&act,0);
try{
....
}
catch(...) {}
}Вот так вот внутри обработчика вызвать программное исключение не получается. Нету ли например каких-либо ключей в gcc или простого способа приучить try срабатывать не ошибки?
Конструкция try {} catch() {} предназначена для ловли исключений, генерируемых средствами самого языка. Обращение по нулевому/неправильному адресу, деление на ноль и т.п. к таковым не относится - такие ситуации обрабатываются программными прерываниями. В UNIX для реагирования на них используются обработчики сигналов. Но единственно правильная реакция на SIGSEGV - напечатать ругательство и аварийно завершиться.В "виндовсе" спасение от проблем - кажущееся. Несмотря на наличие в компиляторе MSVC поддержки так называемого SEH (Structured Exception Handling), при обращении, скажем, по неправильному адресу (в том числе и нулевому) программа, вообще говоря, не может корректно продолжить работу - на это не расчитаны, в частности стандартные библиотеки, да и свой собственный код написать с учетом такого рода сбоев нереально.
В корректно написанной программе ситуации перечисленных видов возникать не должны: если они возникли, то это - ошибка программиста.
Виндовая обработка меня куда больше устраивает. Потому как программными исключениями (ихмо совершенно бестолковая вещь), я ну разве что один раз за всю жизнь пользовался да и то в красоте того кода я сильно сомневаюсь. И когда у тебя несколько метров исходника то ошибку в ней как не старайся сделать достаточно легко. А если программа находится в работе и исправлять её в этот момент поздно, то рассуждения о правильности написания тут уже не греют. Часто есть куда более эффективные способы стабилизировать работу после ошибки, чем тупое игнорирование исключения. А писать сложную обработку сигналов, мне немного геморно.Поэтому меня всё таки больше устоит какое-нибудь элегантное решение, например ответ на мой вопрос.
>[оверквотинг удален]
>пользовался да и то в красоте того кода я сильно сомневаюсь.
>И когда у тебя несколько метров исходника то ошибку в ней
>как не старайся сделать достаточно легко. А если программа находится в
>работе и исправлять её в этот момент поздно, то рассуждения о
>правильности написания тут уже не греют. Часто есть куда более эффективные
>способы стабилизировать работу после ошибки, чем тупое игнорирование исключения. А писать
>сложную обработку сигналов, мне немного геморно.
>
> Поэтому меня всё таки больше устоит какое-нибудь элегантное решение,
>например ответ на мой вопрос.Ну так это и был ответ на ваш вопрос.
Неужели не понятно что после SIGSEGV единственный правильный путь - это напечатать сообщение об ошибке в syslog (если удастся) и завершить работу - чтобы дать возможность скрипту который запускает процессы перезапустить программу и начать ее исполнение с правильного, чистого, состояния? Если был SIGSEGV - память уже коррупнута и позволять программе работать дальше на коррупнутой памяти никак нельзя.
И поскольку ваша программа сейчас еще не в работе а в стадии написания (иначе вы бы не задавали этот вопрос - очевидно что вы именно сейчас задумались о стратегиях обработки ошибок неспроста :) ), мне кажется следует сейчас написать маленький стартер который только то и делает что стартует процесс программы и ждет SIGCHLD от нее и потом перестартует процесс чтобы продолжить работу если сама программа крахнулась; а в самой программе предусмотреть что ее могут запустить не с самого начала, а после краха - типа, записывать промежуточные результаты в файл, или еще как сохранять информацию о том какая последняя стадия была успешной. Если это какий-то сервер, то тут все совсем просто: текущий запрос получает ошибку как результат, сервер перестартует и готов к обработке новых запросов, даже промежуточного состояния записывать не надо.
Я сам писал такие стартеры - причем даже не на Си, а на перле, ничего особо военного тут нет :)
Thank you,elvenic
>Виндовая обработка меня куда больше устраивает. Потому как программными исключениями
>(ихмо совершенно бестолковая вещь), я ну разве что один раз за всю жизнь
>пользовался да и то в красоте того кода я сильно сомневаюсь.Что говорит главным образом о Вашем неумении писать на C++. Использование
программных исключений для обработки программных ошибок при правильной организации
кода (который как минимум автоматически освобождать все ресурсы при откате стека)
экономит уйму сил и времени программиста.>И когда у тебя несколько метров исходника то ошибку в ней как не старайся
>сделать достаточно легко. А если программа находится в работе и исправлять
>её в этот момент поздно, то рассуждения о правильности написания тут уже
>не греют. Часто есть куда более эффективные способы стабилизировать работу
>после ошибки, чем тупое игнорирование исключения. А писать
>сложную обработку сигналов, мне немного геморно.Надежно "стабилизировать" работу программы после получения заслуженного SIGSEGV
невозможно в принципе. Любые попытки в этом направлении относятся к области
шаманских плясок с бубном. Можно только перезапуститься - причем организация
кода должна в идеале позволить хотя бы частично восстановить состояние.> Поэтому меня всё таки больше устоит какое-нибудь элегантное решение,
>например ответ на мой вопрос.Ответ в более внятной форме: концепция SEH не поддерживается ни в одной
известной мне операционной системе, кроме MS Windows. А хотите Вы именно SEH.
Поддержка SEH нужна не на уровне компилятора или языковых трюков, а именно
на уровне ОС, которая при возникновении сбоя вызовет нужный (зарегистрированный
кодом, который сгенерировал компилятор) обработчик.
Тема, между делом, закрыта.... Избавте меня от дальнейшей философии в мой ящик..
>Тема, между делом, закрыта....Gut.
>Избавте меня от дальнейшей философии в мой ящик..
И эти люди запрещают мне ковырять в носу! (C) Вовочка