More Related Content Similar to C++ exceptions (20) More from Platonov Sergey (14) C++ exceptions3. Архитектура Int FP
x86-32 8 8
x86-64 16 16
IBM/360 16 4
z/Architecture 16 16
Itanium 128 128
SPARC 31 32
IBM Cell 4~16 1~4
IBM POWER 32 32
Power Architecture 32 32
Архитектура Int FP
Alpha 32 32
6502 3 0
W65C816S 5 0
PIC microcontroller 1 0
AVR microcontroller 32 0
ARM 32-bit[5]
16 varies
ARM 64-bit[6]
31 32
PDP-11 6 0
MIPS 31 32
4. <1>: DW_TAG_subprogram
DW_AT_name = foo
<2>: DW_TAG_variable
DW_AT_name = b
DW_AT_type = <4>
DW_AT_location = (DW_OP_reg0)
<3>: DW_TAG_variable
DW_AT_name = c
DW_AT_type = <4>
DW_AT_location = (DW_OP_fbreg: -12)
<4>: DW_TAG_base_type
DW_AT_name = int
DW_AT_byte_size = 4
DW_AT_encoding = signed
<5>: DW_TAG_variable
DW_AT_name = a
DW_AT_type = <4>
DW_AT_external = 1
DW_AT_location = (DW_OP_addr: 0)
1: int a;
2: void foo()
3: {
4: register int b;
5: int c;
6: }
DWARF:
http://www.dwarfstd.org/doc/Debugging%20using%20DWARF.pdf
5. 0x00000083: TAG_formal_parameter [4]
AT_name( "x" )
AT_decl_file( "test.c" )
AT_decl_line( 1 )
AT_type( {0x0000005f} ( int ) )
AT_location( 0x00000000
0x00000000 - 0x00000003: ecx
0x00000003 - 0x00000018: ecx )
0x00000090: TAG_formal_parameter [4]
AT_name( "y" )
AT_decl_file( "test.c" )
AT_decl_line( 1 )
AT_type( {0x0000005f} ( int ) )
AT_location( 0x0000001e
0x00000000 - 0x00000003: edx
0x00000003 - 0x00000018: edx )
int mult (int x, int y) { return x*y; }dwarfdump:
http://stackoverflow.com/questions/12252176/getting-calling-conventions-from-dwarf-info
8. Раскручиваем стек сами
struct jmp_buf_splice {
jmp_buf_splice ();
~jmp_buf_splice ();
jmp_buf buf_;
jmp_buf_splice *prev_;
unw_item_t objs_;
};
try блок:
static jmp_buf_splice *root_slice_ = NULL;
jmp_buf_splice::jmp_buf_splice ()
{
objs_ = NULL;
prev_ = root_slice_;
root_slice_ = this;
}
jmp_buf_splice::~jmp_buf_splice ()
{
root_slice_ = prev_;
}
9. struct unw_item_t {
unw_item_t ();
virtual ~unw_item_t ();
void unreg();
unw_item_t *prev_;
};
unw_item_t::unw_item_t ()
{
if (NULL != root_slice_)
{
prev_ = root_slice_->objs_;
root_slice_->objs_ = this;
}
}
unw_item_t::~unw_item_t ()
{
if (NULL != root_slice_ &&
(prev_ != reinterpret_cast <unw_item_t *>(~ 0)))
{
root_slice_->objs_ = prev_;
prev_ = reinterpret_cast <unw_item_t *>(~ 0);
}
}
Само(раз)регистрирующийся элемент:
10. Собственно раскрутка стека:
int throw_slice ( const char *str)
{
jmp_buf_splice *sl = root_slice_;
unw_item_t *obj = root_slice_->objs_;
while (NULL != obj)
{
unw_item_t *tmp = obj;
obj = obj->prev_;
tmp->~unw_item_t ();
}
longjmp (sl->buf_, int(str));
return 0;
}
11. Пример
TRY_BLOCK {
vec_deleter_t<_A> da(new _A[3]);
TRY_BLOCK {
THROW_IN_BLOCK("errorn");
std::cerr << "notreachedn";
}
CATCH_BLOCK_FIN {
std::cerr << "." << __exc;
RETHROW_IN_BLOCK;
}
FIN_BLOCK;
std::cerr << "notreachedn";
}
CATCH_BLOCK_FIN {
std::cerr << ".." << __exc;
}
FIN_BLOCK;
A::A(1)
A::A(2)
A::A(3)
.error
A::~A(3)
A::~A(2)
A::~A(1)
..error
12. Чего не хватает?
● Нельзя бросать исключения в деструкторе
● Потокобезопасность отсутствует
● Экземпляр наследованного от unw_item_t класса может
быть только стековым
● Класс, наследованный от unw_item_t нельзя
агрегировать
● Метод не дружит с аппаратными исключениями
● Удалять брошенный объект-исключение должен тот, кто
его поймал