Nasıl özel durumlar (kamera arkası) c işi | Netgez.com
SORU
21 Kasım 2008, Cuma


Nasıl özel durumlar (kamera arkası) c işi

İnsanların özel durumlar yavaş olduğunu söylüyorlar görüp duruyorum ama hiç bir kanıt görmek. Eğer sormak yerine nasıl özel durumlar bunları kullanmak ne zaman kararları ben sahne arkasında çalışmak soruyorum ve eğer yavaş.

İstisnalar bildiğim kadarıyla iade bir grup ama aynı zamanda dönüş yapıyor durdurmak için gerektiğinde kontrolü yapıyor aynı şeyi. Nasıl durdurmak için ne zaman kontrol? Bir tahmin almak ve özel durum türü tutar ve yeri yığın yığın sonra oraya dönene kadar mı katılan var diyorum. Ayrıca, bir yığın dokunmatik atmak ve her/try olduğunu sadece tahmin ediyorum. AFAİCT dönüş kodu ile benzer bir davranış uygulama aynı süreyi alır. Ama bu bilmek istiyorum, bu yüzden bir tahmin.

Nasıl özel durumlar gerçekten işe yarar mı?

CEVAP
21 Kasım 2008, Cuma


Tahmin yerine, aslında C kod küçük bir parça ile oluşturulan kod bakmaya karar verdim ve biraz eski bir Linux kurun.

class MyException
{
public:
    MyException() { }
    ~MyException() { }
};

void my_throwing_function(bool throwit)
{
    if (throwit)
    	throw MyException();
}

void another_function();
void log(unsigned count);

void my_catching_function()
{
    log(0);
    try
    {
    	log(1);
    	another_function();
    	log(2);
    }
    catch (const MyException& e)
    {
    	log(3);
    }
    log(4);
}

g -m32 -W -Wall -O3 -save-temps -c ile ve oluşturulan Kurul dosyasına baktım derlenmiş.

    .file	"foo.cpp"
    .section	.text._ZN11MyExceptionD1Ev,"axG",@progbits,_ZN11MyExceptionD1Ev,comdat
    .align 2
    .p2align 4,,15
    .weak	_ZN11MyExceptionD1Ev
    .type	_ZN11MyExceptionD1Ev, @function
_ZN11MyExceptionD1Ev:
.LFB7:
    pushl	ëp
.LCFI0:
    movl	%esp, ëp
.LCFI1:
    popl	ëp
    ret
.LFE7:
    .size	_ZN11MyExceptionD1Ev, .-_ZN11MyExceptionD1Ev

_ZN11MyExceptionD1Ev derleyici yıkıcı olmayan satır içi bir kopyası gerekli karar verdim 10**.

.globl __gxx_personality_v0
.globl _Unwind_Resume
    .text
    .align 2
    .p2align 4,,15
.globl _Z20my_catching_functionv
    .type	_Z20my_catching_functionv, @function
_Z20my_catching_functionv:
.LFB9:
    pushl	ëp
.LCFI2:
    movl	%esp, ëp
.LCFI3:
    pushl	ëx
.LCFI4:
    subl	$20, %esp
.LCFI5:
    movl	$0, (%esp)
.LEHB0:
    call	_Z3logj
.LEHE0:
    movl	$1, (%esp)
.LEHB1:
    call	_Z3logj
    call	_Z16another_functionv
    movl	$2, (%esp)
    call	_Z3logj
.LEHE1:
.L5:
    movl	$4, (%esp)
.LEHB2:
    call	_Z3logj
    addl	$20, %esp
    popl	ëx
    popl	ëp
    ret
.L12:
    subl	$1, íx
    movl	êx, ëx
    je	.L16
.L14:
    movl	ëx, (%esp)
    call	_Unwind_Resume
.LEHE2:
.L16:
.L6:
    movl	êx, (%esp)
    call	__cxa_begin_catch
    movl	$3, (%esp)
.LEHB3:
    call	_Z3logj
.LEHE3:
    call	__cxa_end_catch
    .p2align 4,,3
    jmp	.L5
.L11:
.L8:
    movl	êx, ëx
    .p2align 4,,6
    call	__cxa_end_catch
    .p2align 4,,6
    jmp	.L14
.LFE9:
    .size	_Z20my_catching_functionv, .-_Z20my_catching_functionv
    .section	.gcc_except_table,"a",@progbits
    .align 4
.LLSDA9:
    .byte	0xff
    .byte	0x0
    .uleb128 .LLSDATT9-.LLSDATTD9
.LLSDATTD9:
    .byte	0x1
    .uleb128 .LLSDACSE9-.LLSDACSB9
.LLSDACSB9:
    .uleb128 .LEHB0-.LFB9
    .uleb128 .LEHE0-.LEHB0
    .uleb128 0x0
    .uleb128 0x0
    .uleb128 .LEHB1-.LFB9
    .uleb128 .LEHE1-.LEHB1
    .uleb128 .L12-.LFB9
    .uleb128 0x1
    .uleb128 .LEHB2-.LFB9
    .uleb128 .LEHE2-.LEHB2
    .uleb128 0x0
    .uleb128 0x0
    .uleb128 .LEHB3-.LFB9
    .uleb128 .LEHE3-.LEHB3
    .uleb128 .L11-.LFB9
    .uleb128 0x0
.LLSDACSE9:
    .byte	0x1
    .byte	0x0
    .align 4
    .long	_ZTI11MyException
.LLSDATT9:

Sürpriz! Normal kod yolu üzerindeki tüm ek talimatlar vardır. Derleyici yerine out-of-line düzeltme kod blokları ekstra işlev sonunda aslında çalıştırılabilir ayrı bir bölüme koymak olan bir tablo ile başvurulan oluşturdu. Tüm çalışma masaları (_ZTI11MyException typeinfo for MyException) dayalı standart Kütüphanesi tarafından perde arkasında yapılır.

TAMAM, bu aslında benim için bir sürpriz değildi, ben bu derleyici bunu nasıl yaptığını zaten biliyordu. Derleme çıktısı ile devam ediyor:

    .text
    .align 2
    .p2align 4,,15
.globl _Z20my_throwing_functionb
    .type	_Z20my_throwing_functionb, @function
_Z20my_throwing_functionb:
.LFB8:
    pushl	ëp
.LCFI6:
    movl	%esp, ëp
.LCFI7:
    subl	$24, %esp
.LCFI8:
    cmpb	$0, 8(ëp)
    jne	.L21
    leave
    ret
.L21:
    movl	$1, (%esp)
    call	__cxa_allocate_exception
    movl	$_ZN11MyExceptionD1Ev, 8(%esp)
    movl	$_ZTI11MyException, 4(%esp)
    movl	êx, (%esp)
    call	__cxa_throw
.LFE8:
    .size	_Z20my_throwing_functionb, .-_Z20my_throwing_functionb

Burada bir istisna atma kodunu görüyoruz. Sadece bir özel durum olabilir çünkü ekstra yükü vardı, belli ki aslında atma ve bir özel durum yakalamak çok yük var. Çoğu __cxa_throw hangi gerekir: içinde gizlidir

  • Bu özel durum için bir iÅŸleyici bulana kadar durum tabloları yardımıyla yığın yürüme mesafesinde.
  • Bu iÅŸleyici bulunana kadar yığın gevÅŸeyin.
  • Aslında iÅŸleyicisi arayın.

Sadece bir değer döndüren maliyeti ile karşılaştırın, özel durumlar ve olağanüstü getiriler için sadece kullanılmalıdır neden bakın.

Bitirmek için, montaj dosyanın geri kalanını:

    .weak	_ZTI11MyException
    .section	.rodata._ZTI11MyException,"aG",@progbits,_ZTI11MyException,comdat
    .align 4
    .type	_ZTI11MyException, @object
    .size	_ZTI11MyException, 8
_ZTI11MyException:
    .long	_ZTVN10__cxxabiv117__class_type_infoE 8
    .long	_ZTS11MyException
    .weak	_ZTS11MyException
    .section	.rodata._ZTS11MyException,"aG",@progbits,_ZTS11MyException,comdat
    .type	_ZTS11MyException, @object
    .size	_ZTS11MyException, 14
_ZTS11MyException:
    .string	"11MyException"

Typeinfo verileri.

    .section	.eh_frame,"a",@progbits
.Lframe1:
    .long	.LECIE1-.LSCIE1
.LSCIE1:
    .long	0x0
    .byte	0x1
    .string	"zPL"
    .uleb128 0x1
    .sleb128 -4
    .byte	0x8
    .uleb128 0x6
    .byte	0x0
    .long	__gxx_personality_v0
    .byte	0x0
    .byte	0xc
    .uleb128 0x4
    .uleb128 0x4
    .byte	0x88
    .uleb128 0x1
    .align 4
.LECIE1:
.LSFDE3:
    .long	.LEFDE3-.LASFDE3
.LASFDE3:
    .long	.LASFDE3-.Lframe1
    .long	.LFB9
    .long	.LFE9-.LFB9
    .uleb128 0x4
    .long	.LLSDA9
    .byte	0x4
    .long	.LCFI2-.LFB9
    .byte	0xe
    .uleb128 0x8
    .byte	0x85
    .uleb128 0x2
    .byte	0x4
    .long	.LCFI3-.LCFI2
    .byte	0xd
    .uleb128 0x5
    .byte	0x4
    .long	.LCFI5-.LCFI3
    .byte	0x83
    .uleb128 0x3
    .align 4
.LEFDE3:
.LSFDE5:
    .long	.LEFDE5-.LASFDE5
.LASFDE5:
    .long	.LASFDE5-.Lframe1
    .long	.LFB8
    .long	.LFE8-.LFB8
    .uleb128 0x4
    .long	0x0
    .byte	0x4
    .long	.LCFI6-.LFB8
    .byte	0xe
    .uleb128 0x8
    .byte	0x85
    .uleb128 0x2
    .byte	0x4
    .long	.LCFI7-.LCFI6
    .byte	0xd
    .uleb128 0x5
    .align 4
.LEFDE5:
    .ident	"GCC: (GNU) 4.1.2 (Ubuntu 4.1.2-0ubuntu4)"
    .section	.note.GNU-stack,"",@progbits

Daha özel tabloları ve çeşitli ekstra bilgi işleme.

Bu yüzden, sonuç, en azından GCC Linux: maliyet ekstra boşluk (işleyicileri ve tablolar) olsun ya da olmasın istisnalar atılmış, artı ekstra maliyet ayrıştırma tabloları ve yürütme işleyicileri zaman bir istisna atılır. Hata kodları yerine istisnalar kullanın ve bir hata nadirdir olabilirdaha hızlıhatalar için test yükü yok artık beri.

Daha fazla bilgi isterseniz, özellikle ne __cxa_ tüm fonksiyonları, geldikleri özgün belirtimi bkz:

Bunu PaylaÅŸ:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VÄ°DEO

Rastgele Yazarlar

  • dougownsall

    dougownsall

    7 EKÄ°M 2007
  • Howard Pinsky

    Howard Pinsk

    6 AÄžUSTOS 2006
  • superflyy88

    superflyy88

    8 ÅžUBAT 2009