C++ exception context

Discussion in 'C++' started by jg, Apr 17, 2007.

  1. jg

    jg Guest

    Can someone explain what the standard says about
    exception context ? For example, suppose bar() always throw
    an exception, is the value of g undefined or 1 after the handler
    (empty in this case) returns ?

    Thanks
    JG

    foo()
    {
    int g=0;
    try {
    g++;
    bar(); // bar() throw an exception
    } catch (...)
    }
    printf("g=%d\n", g);
    }
     
    jg, Apr 17, 2007
    #1
    1. Advertising

  2. jg

    Ian Collins Guest

    jg wrote:
    > Can someone explain what the standard says about
    > exception context ? For example, suppose bar() always throw
    > an exception, is the value of g undefined or 1 after the handler
    > (empty in this case) returns ?
    >
    > Thanks
    > JG
    >
    > foo()
    > {
    > int g=0;


    The scope of g is foo(), so g will be 1.

    > try {
    > g++;
    > bar(); // bar() throw an exception
    > } catch (...)
    > }
    > printf("g=%d\n", g);
    > }
    >



    --
    Ian Collins.
     
    Ian Collins, Apr 17, 2007
    #2
    1. Advertising

  3. jg

    Andre Kostur Guest

    "jg" <> wrote in news:1176764745.712480.47890
    @y80g2000hsf.googlegroups.com:

    > Can someone explain what the standard says about
    > exception context ? For example, suppose bar() always throw
    > an exception, is the value of g undefined or 1 after the handler
    > (empty in this case) returns ?
    >
    > Thanks
    > JG
    >
    > foo()
    > {
    > int g=0;
    > try {
    > g++;
    > bar(); // bar() throw an exception
    > } catch (...)
    > }
    > printf("g=%d\n", g);
    > }
    >
    >


    I'm not sure why you would think that bar() would have any effect on g.
    The g++ line would have finished executing before bar() is called. An
    exception within a try{} block doesn't somehow invalidate the code that was
    executed up to the point of the exception.
     
    Andre Kostur, Apr 17, 2007
    #3
  4. jg

    jg Guest

    <<Ian Collins>>
    > The scope of g is foo(), so g will be 1.


    So, for the following, glb will be 2.

    int glb=1;

    void bar()
    {
    glb++;
    throw 1;
    }

    foo()
    try {
    bar();
    } catch (...)
    }
    printf("glb=%d\n", glb);
    }


    << Andre Kostur>>
    >
    > I'm not sure why you would think that bar() would have any effect on g.
    > The g++ line would have finished executing before bar() is called. An
    > exception within a try{} block doesn't somehow invalidate the code that was
    > executed up to the point of the exception.


    Since a compiler will allocate g into a register, that same register
    may be reused (write/use) by bar(). Well, the value of the register
    must be saved before being used by bar(). I am just wondering
    how a compiler knows where to restore the value of g....

    Thanks.
    jg
    used by bar(), I am wondering how a hand
     
    jg, Apr 17, 2007
    #4
  5. jg

    Ian Collins Guest

    jg wrote:
    > <<Ian Collins>>
    >
    >>The scope of g is foo(), so g will be 1.

    >
    >
    > So, for the following, glb will be 2.
    >

    Why would it be anything else?

    > int glb=1;
    >
    > void bar()
    > {
    > glb++;
    > throw 1;
    > }
    >
    >
    >
    > Since a compiler will allocate g into a register, that same register
    > may be reused (write/use) by bar(). Well, the value of the register
    > must be saved before being used by bar(). I am just wondering
    > how a compiler knows where to restore the value of g....
    >

    Why would it allocate g into a register? g is a global variable, an
    address in memory, that's all.

    --
    Ian Collins.
     
    Ian Collins, Apr 17, 2007
    #5
  6. jg

    James Kanze Guest

    On Apr 17, 1:05 am, "jg" <> wrote:
    > Can someone explain what the standard says about
    > exception context ? For example, suppose bar() always throw
    > an exception, is the value of g undefined or 1 after the handler
    > (empty in this case) returns ?


    > foo()
    > {
    > int g=0;
    > try {
    > g++;
    > bar(); // bar() throw an exception
    > } catch (...)
    > }
    > printf("g=%d\n", g);
    > }


    In this case, no. The usual C++ rules apply: values will
    reflect all changes before the last sequence point, and none of
    the changes after the next one. Anything which changes with no
    intervening sequence point is up in the air. Throwing an
    exception is a sequence point, but don't forget that the order
    of evaluation of an expression is not specified, so something
    like the following can be very problematic:

    f( g++, bar() ) ;

    If bar() throws, g may or may not have been incremented.

    Be careful, too, because sequence points only define a partial
    ordering. For example, given:
    f( auto_ptr( new Toto ), bar() ) ;
    one possible ordering is:
    tmp = new Toto
    bar()
    auto_ptr( tmp )
    If bar() throws, you've got a memory leak.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Apr 17, 2007
    #6
  7. jg

    Howard Guest

    "jg" <> wrote in message
    news:...

    > foo()
    > {
    > int g=0;
    > try {
    > g++;
    > bar(); // bar() throw an exception
    > } catch (...)


    Not an answer to your question, but...
    shouldn't there be a { here?

    > }
    > printf("g=%d\n", g);
    > }
    >


    -Howard
     
    Howard, Apr 17, 2007
    #7
  8. jg

    jg Guest

    Thanks for answering my questions.

    I also played with it and looked at the code generated. It looks
    that the variables, even locals, will be stored into memory before
    calling bar(), which is within try block and may throw an exception.

    In a C program (not C++), a local variable usually stays within a
    register
    accross a call (a performance advantage over C++); whereas in C++, a
    local
    variable cannot stay in a register accross a call within a try block.

    jg

    On Apr 17, 2:51 am, James Kanze <> wrote:
    > On Apr 17, 1:05 am, "jg" <> wrote:
    >
    > > Can someone explain what the standard says about
    > > exception context ? For example, suppose bar() always throw
    > > an exception, is the value of g undefined or 1 after the handler
    > > (empty in this case) returns ?
    > > foo()
    > > {
    > > int g=0;
    > > try {
    > > g++;
    > > bar(); // bar() throw an exception
    > > } catch (...)
    > > }
    > > printf("g=%d\n", g);
    > > }

    >
    > In this case, no. The usual C++ rules apply: values will
    > reflect all changes before the last sequence point, and none of
    > the changes after the next one. Anything which changes with no
    > intervening sequence point is up in the air. Throwing an
    > exception is a sequence point, but don't forget that the order
    > of evaluation of an expression is not specified, so something
    > like the following can be very problematic:
    >
    > f( g++, bar() ) ;
    >
    > If bar() throws, g may or may not have been incremented.
    >
    > Be careful, too, because sequence points only define a partial
    > ordering. For example, given:
    > f( auto_ptr( new Toto ), bar() ) ;
    > one possible ordering is:
    > tmp = new Toto
    > bar()
    > auto_ptr( tmp )
    > If bar() throws, you've got a memory leak.
    >
    > --
    > James Kanze (GABI Software) email:
    > Conseils en informatique orientée objet/
    > Beratung in objektorientierter Datenverarbeitung
    > 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    jg, Apr 17, 2007
    #8
  9. jg

    Andre Kostur Guest

    jg <> wrote in news:1176834633.458139.176790
    @y5g2000hsa.googlegroups.com:

    > Thanks for answering my questions.
    >
    > I also played with it and looked at the code generated. It looks
    > that the variables, even locals, will be stored into memory before
    > calling bar(), which is within try block and may throw an exception.
    >
    > In a C program (not C++), a local variable usually stays within a
    > register
    > accross a call (a performance advantage over C++); whereas in C++, a
    > local
    > variable cannot stay in a register accross a call within a try block.


    That's a compiler quality of implementation issue, not a C++ lanugage
    issue.
     
    Andre Kostur, Apr 17, 2007
    #9
  10. jg

    James Kanze Guest

    jg wrote:
    > I also played with it and looked at the code generated. It looks
    > that the variables, even locals, will be stored into memory before
    > calling bar(), which is within try block and may throw an exception.


    > In a C program (not C++), a local variable usually stays
    > within a register accross a call (a performance advantage over
    > C++); whereas in C++, a local variable cannot stay in a
    > register accross a call within a try block.


    It depends totally on the implementation, and exceptions have
    very little effect here. Different implementations have
    different conventions regarding what must be saved across the
    context of a function call. Back when I was regularly working
    on Intel architecture, for example, the convention was that a
    function could use any register it wanted: it only had to
    restore BP (the frame pointer), SP (obviously:)) and the
    segment registers. A compiler could not leave a value in a
    register, and expect it to be there after a function call.
    Today, on my Sparc, 16 registers are guaranteed safe, and a
    compiler can leave a value in one of them even when calling a
    function which may throw.

    Exceptions affect optimization in two ways. First, they add
    control flow paths which the compiler must take into account.
    There are probably cases where this will result in saving a
    value to memory, where it would otherwise be left in a register,
    but they probably aren't very frequent. Secondly, it means that
    any time a function which may throw is called, the stack
    structure must be "clean"; it must be possible to walk back up
    the stack using standard mechanisms. In practice, I don't think
    that this ever affects optimization; I'm not aware of a compiler
    that doesn't systematically build a clean stack structure in a
    non-leaf function.

    Exceptions can also have a positive effect on optimization.
    First, because the test for the error condition simply isn't
    present in the code of the intermediate functions, and secondly,
    because the data used by the exception handling is out of line,
    possibly in a separate segment, so the resulting function is
    smaller, and more likely to fit into cache.

    In practice, both effects seem to be pretty negligeable, and the
    choix between exceptions or another error reporting mechanism
    should be based on design, without regarding performance. Do
    what's right; the probability that it will cause a performance
    problem is so low that it's not worth worrying about.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Apr 18, 2007
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. VS_NET_DEV
    Replies:
    2
    Views:
    3,802
    jenny
    May 25, 2004
  2. =?Utf-8?B?U3VuU21pbGU=?=
    Replies:
    0
    Views:
    707
    =?Utf-8?B?U3VuU21pbGU=?=
    Jan 10, 2006
  3. Flip Rayner
    Replies:
    1
    Views:
    657
    bruce barker
    Jan 23, 2007
  4. asd
    Replies:
    1
    Views:
    435
    www.pulpjava.com
    Nov 9, 2006
  5. Jani Tiainen
    Replies:
    3
    Views:
    1,021
    Jani Tiainen
    Aug 27, 2007
Loading...

Share This Page