Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 92129
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 10, 20262026-05-10T23:08:19+00:00 2026-05-10T23:08:19+00:00

I keep seeing people say that exceptions are slow, but I never see any

  • 0

I keep seeing people say that exceptions are slow, but I never see any proof. So, instead of asking if they are, I will ask how do exceptions work behind the scenes, so I can make decisions of when to use them and whether they are slow.

From what I know, exceptions are the same as doing a return bunch of times, except that it also checks after each return whether it needs to do another one or to stop. How does it check when to stop returning? I guess there is a second stack that holds the type of the exception and a stack location, it then does returns until it gets there. I am also guessing that the only time this second stack is touched is on a throw and on each try/catch. AFAICT implementing a similar behaviour with return codes would take the same amount of time. But this is all just a guess, so I want to know what really happens.

How do exceptions really work?

  • 1 1 Answer
  • 3 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. 2026-05-10T23:08:19+00:00Added an answer on May 10, 2026 at 11:08 pm

    Instead of guessing, I decided to actually look at the generated code with a small piece of C++ code and a somewhat old Linux install.

    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); } 

    I compiled it with g++ -m32 -W -Wall -O3 -save-temps -c, and looked at the generated assembly file.

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

    _ZN11MyExceptionD1Ev is MyException::~MyException(), so the compiler decided it needed a non-inline copy of the destructor.

    .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   %ebp .LCFI2:     movl    %esp, %ebp .LCFI3:     pushl   %ebx .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    %ebx     popl    %ebp     ret .L12:     subl    $1, %edx     movl    %eax, %ebx     je  .L16 .L14:     movl    %ebx, (%esp)     call    _Unwind_Resume .LEHE2: .L16: .L6:     movl    %eax, (%esp)     call    __cxa_begin_catch     movl    $3, (%esp) .LEHB3:     call    _Z3logj .LEHE3:     call    __cxa_end_catch     .p2align 4,,3     jmp .L5 .L11: .L8:     movl    %eax, %ebx     .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: 

    Surprise! There are no extra instructions at all on the normal code path. The compiler instead generated extra out-of-line fixup code blocks, referenced via a table at the end of the function (which is actually put on a separate section of the executable). All the work is done behind the scenes by the standard library, based on these tables (_ZTI11MyException is typeinfo for MyException).

    OK, that was not actually a surprise for me, I already knew how this compiler did it. Continuing with the assembly output:

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

    Here we see the code for throwing an exception. While there was no extra overhead simply because an exception might be thrown, there is obviously a lot of overhead in actually throwing and catching an exception. Most of it is hidden within __cxa_throw, which must:

    • Walk the stack with the help of the exception tables until it finds a handler for that exception.
    • Unwind the stack until it gets to that handler.
    • Actually call the handler.

    Compare that with the cost of simply returning a value, and you see why exceptions should be used only for exceptional returns.

    To finish, the rest of the assembly file:

        .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" 

    The typeinfo data.

        .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 

    Even more exception handling tables, and assorted extra information.

    So, the conclusion, at least for GCC on Linux: the cost is extra space (for the handlers and tables) whether or not exceptions are thrown, plus the extra cost of parsing the tables and executing the handlers when an exception is thrown. If you use exceptions instead of error codes, and an error is rare, it can be faster, since you do not have the overhead of testing for errors anymore.

    In case you want more information, in particular what all the __cxa_ functions do, see the original specification they came from:

    • Itanium C++ ABI
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I am keep seeing such errors but the xcode never shows the line that
I keep seeing people writing wrappers for, say a module written in X language
I keep seeing people using doubles in C#. I know I read somewhere that
I keep seeing what appears to be a memory leak - but I can't
I keep seeing documentation saying that its not possible to send to a remote
I keep seeing warnings not to use global variables in JavaScript, but it seems
I keep on hearing and seeing people mention ANSI-SPARC, we even have such a
I have a simple question about usage of Hibernate. I keep seeing people using
I keep seeing these errors in our error log. Any ideas how i can
I am trying to learn jQuery. I keep seeing people using different methods of

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.