LINUX.ORG.RU

обработка исключений в C++


0

0

Привет !!! Есть такая программка :

// test.cc

void main() { try { int a = 2; int b = 0; a /= b; } catch(...) { } }

Вопрос: с какими опциями её надо откомпилировать чтобы сработало исключение. Если компилить например так "g++ test.cc -o test" то прога завершается с ошибкой "Floating point exception (core dumped)".

anonymous

Re

Ни с какими. C++-ексепции там не возникает. Генерируется сигнал SIGFPE. Так что try/catch там вообще не по делу.

Debugger
()

гы
очевидно на лицо факт наличия отсутствия полного понимания сути 
исключительных ситуаций и языковых особенностей. как выразился? 
все на много проще... исключения - это ситуации, 
которые вы >сами< выделяете как исключительные. 
и сами же генерите исключение
и сами же его обрабатываете...

для вашего (извините) тупого примера
if (b == 0)
{
   my_exc exc("какого хрена!");
   throw(exc);
}

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

anonymous
()
Ответ на: комментарий от anonymous

Re

Кста, просветите невежду (блин, совсем не писал на плюсах под униксами), что будет, если кинуть ексепцию из обработчика сигнала. Ну, понятно, чем навеяна такая мысль: сделать обработчик SIGFPE и кидать нужные ексепции из него. По великому замыслу, у первого анонимуса тогда все получится :) Или не получится? :)

Debugger
()
Ответ на: Re от Debugger

Не получится.

Хотя наверно можно использовать грязные хаки с setjmp()/longjmp()

abbr
()
Ответ на: Re от Debugger

дык ясен пень, что не получится
и я предлагаю вам самому додуматься почему. (подсказка, обратите внимание на очередность вызовов обработчика сигнала и ловушки исключения)
ну а для развлечения ума, так сказать, предлагаю еще и прикинуть, что получиться если форкать детачнутый процесс в обработчике :)

anonymous
()
Ответ на: комментарий от abbr

>Не получится. Ошибаешся ...

>Хотя наверно можно использовать грязные хаки с setjmp()/longjmp() Именно так и делают ...

sS ★★★★★
()
Ответ на: комментарий от sS

>>Хотя наверно можно использовать грязные хаки с setjmp()/longjmp()

> Именно так и делают ...

а хто деструкторы объектов на стеке вызывает (с сохранением порядка вызова), ручками что-ли?

anonymous
()
Ответ на: комментарий от anonymous

>а хто деструкторы объектов на стеке вызывает (с сохранением порядка вызова), ручками что-ли?

ты не в ту сторону подумал ;)

Описываю только принцип - реальный код чуть сложнее

#define _try try { Context C; \ // при вызове конструктора пихаем контекст в стек
int e=_setjmp(C) \ // в случае ловли сигнала вернемся сюда из обработчика сигнала с помощбю longjmp() с e != 0
if(e) trow(e) \ // тут работает стандартный плюсовый trow
else

#define _catch(E) } catch(E) // неявный вызов деструктора убираем контекст из стека





sS ★★★★★
()
Ответ на: комментарий от sS

> #define _try try { Context C; \ // при вызове конструктора пихаем контекст в стек 
> int e=_setjmp(C) \ // в случае ловли сигнала вернемся сюда из обработчика сигнала с помощбю longjmp() с e != 0 
> if(e) trow(e) \ // тут работает стандартный плюсовый trow 
> else 

> #define _catch(E) } catch(E) // неявный вызов деструктора убираем контекст из стека

а между else и longjmp() никаких объектов не создаётся?!

anonymous
()
Ответ на: комментарий от anonymous

>а между else и longjmp() никаких объектов не создаётся?!

Ну не совсем в лоб а через что то типа

#define SaveContext(O) O;\ {int e=setjmp(C)\ if(e) trow(e)}

sS ★★★★★
()
Ответ на: комментарий от sS

> Ну не совсем в лоб а через что то типа 

> #define SaveContext(O) O;\ {int e=setjmp(C)\ if(e) trow(e)}

я плохо объяснил, проблема следующая: после сохранения контекста и 
первого вызова setjmp могут создаваться объекты с недефолтными 
деструкторами, во время вызова longjmp при переходе на более высокий 
уровень стека эти деструкторы надо вызвать, кто это делает?

anonymous
()
Ответ на: комментарий от anonymous

>я плохо объяснил, проблема следующая: после сохранения контекста и 
первого вызова setjmp могут создаваться объекты с недефолтными 
деструкторами, во время вызова longjmp при переходе на более высокий 
уровень стека эти деструкторы надо вызвать, кто это делает?

Видимо это я плохо обяснил смысл данного макроса ;)

#include <math.h>
#include <stdio.h>
#include <iostream.h>
#include "except.hpp"

class Test {
char* name;
public:
Test(char* n):name(0L)  { 
int len;
if(n) {
len = strlen(n);
if(len) {
 name = new char[len+1];
 strcpy(name,n);
 }
}
cout << "Call Test("<< GetName() <<") constructor:" << endl;
}

~Test() { 
cout << "Call Test("<< GetName() <<") destructor:" << endl;
if(name)
   delete name;
}

char* GetName() {return name;}
void ThrowTestException() {throw(this);}
};

int main(int argc , char** argv)
{
  int* A=0;
  int  B=1;

  __ExceptLib.SetSystemException(SIGSEGV,AT_HANDLED);
  __ExceptLib.SetSystemException(SIGFPE,AT_HANDLED);

 __try { 
         SaveContext(Test T1("T1"));
         SaveContext(Test T2("T2"));

 __try { 
         SaveContext(Test T3("T3"));
         (*A)=B/B--;  
	 SaveContext(Test T4("T4"));


       } __catch(SysException e) {
                      cout << "Signal "<< e << endl;
       } catch(Test* t) {
                      cout << "Test exception "<<  endl;
       } catch(...) {
                      cout << "oops... "<<  endl;
       }

 __try { 

         SaveContext(Test T5("T5"));
         SaveContext(Test T6("T6"));
         SaveContext(Test T7("T7"));
         (*A)=B/--B;  
	 SaveContext(Test T8("T8"));

       } __catch(SysException e) {
                      cout << "Signal "<< e << endl;
       } catch(Test* t) {
                      cout << "Test exception " <<  endl;
       } catch(...) {
                      cout << "oops... "<<  endl;
       }


         SaveContext(Test T9("T9"));
         SaveContext(Test T10("T10"));
         SaveContext(Test T11("T11"));
         SaveContext(Test T12("T12"));
         T1.ThrowTestException();
   

       } __catch(SysException e) {
                      cout << "Signal "<< e << endl;
       } catch(Test* t) {
                      cout << "Test exception " <<  endl;
       } catch(...) {
                      cout << "oops... "<<  endl;
       }

 return 0;
}

// подробности реализации стека контекстов и обработчика сигналов опущены

ss@xantippe:~/Work/libExcept$ ./test1
Call Test(T1) constructor:
Call Test(T2) constructor:
Call Test(T3) constructor:
Call Test(T3) destructor:
Signal 11
Call Test(T5) constructor:
Call Test(T6) constructor:
Call Test(T7) constructor:
Call Test(T7) destructor:
Call Test(T6) destructor:
Call Test(T5) destructor:
Signal 8
Call Test(T9) constructor:
Call Test(T10) constructor:
Call Test(T11) constructor:
Call Test(T12) constructor:
Call Test(T12) destructor:
Call Test(T11) destructor:
Call Test(T10) destructor:
Call Test(T9) destructor:
Call Test(T2) destructor:
Call Test(T1) destructor:
Test exception


Возможно немного громоздко но работает ...


sS ★★★★★
()
Ответ на: комментарий от sS

PS: обрати внимание как меняется B

Это не баг - это фича ;)

sS ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.