Question on vector at()

Discussion in 'C++' started by Alexander Dong Back Kim, Mar 14, 2008.

  1. Dear all,

    I want to create a method that return an element in a vector by
    selecting the element position by vector's at().

    The method should be look like

    vector<Apple> _appleBox;

    Apple & AppleBox::GetApple (int index);

    but my question is when _appleBox.at(index) is called inside of the
    method GetApple, if it is out of range, an exception will be occured
    so the exception handling might be

    try
    {
    return _appleBox.at(index);
    }
    catch (out_of_range e)
    {
    return ???;
    }

    What should be returned when process fall into the catch statement? I
    tried NULL but seems it doesn't work at all.

    Any idea or advice?

    cheers,
     
    Alexander Dong Back Kim, Mar 14, 2008
    #1
    1. Advertising

  2. Alexander Dong Back Kim

    YYweii Guest

    On Mar 14, 11:57 am, Alexander Dong Back Kim <>
    wrote:
    > Dear all,
    >
    > I want to create a method that return an element in a vector by
    > selecting the element position by vector's at().
    >
    > The method should be look like
    >
    > vector<Apple> _appleBox;
    >
    > Apple & AppleBox::GetApple (int index);
    >
    > but my question is when _appleBox.at(index) is called inside of the
    > method GetApple, if it is out of range, an exception will be occured
    > so the exception handling might be
    >
    > try
    > {
    > return _appleBox.at(index);}
    >
    > catch (out_of_range e)
    > {
    > return ???;
    >
    > }
    >
    > What should be returned when process fall into the catch statement? I
    > tried NULL but seems it doesn't work at all.
    >
    > Any idea or advice?
    >
    > cheers,


    return Apple * instead of Apple & in function AppleBox::GetApple
     
    YYweii, Mar 14, 2008
    #2
    1. Advertising

  3. Alexander Dong Back Kim

    red floyd Guest

    Alexander Dong Back Kim wrote:
    > Dear all,
    >
    > I want to create a method that return an element in a vector by
    > selecting the element position by vector's at().
    >
    > The method should be look like
    >
    > vector<Apple> _appleBox;
    >
    > Apple & AppleBox::GetApple (int index);
    >
    > but my question is when _appleBox.at(index) is called inside of the
    > method GetApple, if it is out of range, an exception will be occured
    > so the exception handling might be
    >
    > try
    > {
    > return _appleBox.at(index);
    > }
    > catch (out_of_range e)
    > {
    > return ???;
    > }
    >
    > What should be returned when process fall into the catch statement? I
    > tried NULL but seems it doesn't work at all.
    >
    > Any idea or advice?
    >


    Don't catch it in GetApple. Odds are that you won't know what to do
    with it anyways. Let it propagate up to the caller, who will probably
    have a better idea of what it wants to do with the exception.

    That's the beauty of exceptions. They let the exceptional condition be
    handled at the "right" level. In this case, GetApple is too low-level
    to know what to do properly.
     
    red floyd, Mar 14, 2008
    #3
  4. Alexander Dong Back Kim

    thomas Guest

    On Mar 14, 11:57 am, Alexander Dong Back Kim <>
    wrote:
    > Dear all,
    >
    > I want to create a method that return an element in a vector by
    > selecting the element position by vector's at().
    >
    > The method should be look like
    >
    > vector<Apple> _appleBox;
    >
    > Apple & AppleBox::GetApple (int index);
    >
    > but my question is when _appleBox.at(index) is called inside of the
    > method GetApple, if it is out of range, an exception will be occured
    > so the exception handling might be
    >
    > try
    > {
    >   return _appleBox.at(index);}
    >
    > catch (out_of_range e)
    > {
    >   return ???;
    >
    > }
    >
    > What should be returned when process fall into the catch statement? I
    > tried NULL but seems it doesn't work at all.
    >
    > Any idea or advice?
    >
    > cheers,


    Why not check if "index" is out of range before accessing it?
    Even if you try to do it in this way, I think "null" can be returned.
    But the caller must make sure that it's not null before calling its
    member functions.
     
    thomas, Mar 14, 2008
    #4
  5. Alexander Dong Back Kim

    red floyd Guest

    thomas wrote:
    > On Mar 14, 11:57 am, Alexander Dong Back Kim <>
    > wrote:
    >> Dear all,
    >>
    >> I want to create a method that return an element in a vector by
    >> selecting the element position by vector's at().
    >>
    >> The method should be look like
    >>
    >> vector<Apple> _appleBox;
    >>
    >> Apple & AppleBox::GetApple (int index);
    >>
    >> but my question is when _appleBox.at(index) is called inside of the
    >> method GetApple, if it is out of range, an exception will be occured
    >> so the exception handling might be
    >>
    >> try
    >> {
    >> return _appleBox.at(index);}
    >>
    >> catch (out_of_range e)
    >> {
    >> return ???;
    >>
    >> }
    >>
    >> What should be returned when process fall into the catch statement? I
    >> tried NULL but seems it doesn't work at all.
    >>
    >> Any idea or advice?
    >>
    >> cheers,

    >
    > Why not check if "index" is out of range before accessing it?
    > Even if you try to do it in this way, I think "null" can be returned.
    > But the caller must make sure that it's not null before calling its
    > member functions.


    No, NULL can't be returned -- he's returning a reference, not a pointer.
    Repeat after me -- A REFERENCE IS NOT A POINTER
     
    red floyd, Mar 14, 2008
    #5
  6. Alexander Dong Back Kim wrote:
    > try
    > {
    > return _appleBox.at(index);
    > }
    > catch (out_of_range e)
    > {
    > return ???;
    > }


    Perhaps a different design could be better here?

    Usually indexing out of boundaries means one of two things:

    1) It's an error, ie. a bug in the code. In this case an assert() is
    usually better than throwing (because you can get the whole call stack
    easily with a debugger).

    2) In a few designs it's not an error at all, but intended behavior. In
    these cases usually indexing out of boundaries simply returns some
    default value of the element type. In that case checking the boundaries
    before indexing (and returning the default value if it's out of
    boundaries) is better than using at(), which throws an exception.

    A third possibility where and index may be in danger of being out of
    boundaries is with invalid user input. However, throwing an exception in
    this case would usually be very wrong. The correct way is to validate
    the user input before even trying to index anything.

    I can't think of many applications where at() throwing an exception
    would be in any way a desirable thing. (As mentioned, to catch
    programming errors IMO using assert() is better.)
     
    Juha Nieminen, Mar 14, 2008
    #6
  7. Alexander Dong Back Kim

    Jeff Schwab Guest

    Juha Nieminen wrote:
    > Alexander Dong Back Kim wrote:
    >> try
    >> {
    >> return _appleBox.at(index);
    >> }
    >> catch (out_of_range e)
    >> {
    >> return ???;
    >> }

    >
    > Perhaps a different design could be better here?
    >
    > Usually indexing out of boundaries means one of two things:
    >
    > 1) It's an error, ie. a bug in the code. In this case an assert() is
    > usually better than throwing (because you can get the whole call stack
    > easily with a debugger).


    <gasp> Strongly disagree. </>

    > 2) In a few designs it's not an error at all, but intended behavior. In
    > these cases usually indexing out of boundaries simply returns some
    > default value of the element type. In that case checking the boundaries
    > before indexing (and returning the default value if it's out of
    > boundaries) is better than using at(), which throws an exception.


    Agreed.

    > A third possibility where and index may be in danger of being out of
    > boundaries is with invalid user input. However, throwing an exception in
    > this case would usually be very wrong. The correct way is to validate
    > the user input before even trying to index anything.


    Also generally true.

    > I can't think of many applications where at() throwing an exception
    > would be in any way a desirable thing. (As mentioned, to catch
    > programming errors IMO using assert() is better.)


    Huh? The exception is *exactly* the right solution, for the reasons red
    floyd already explained.
     
    Jeff Schwab, Mar 14, 2008
    #7
  8. Jeff Schwab wrote:
    >> I can't think of many applications where at() throwing an exception
    >> would be in any way a desirable thing. (As mentioned, to catch
    >> programming errors IMO using assert() is better.)

    >
    > Huh? The exception is *exactly* the right solution, for the reasons red
    > floyd already explained.


    Could you please explain to me why is that?

    If indexing out of boundaries at some place is an indication of a
    programming error, ie. a bug, the best course of action is to report
    immediately about this detected error, at the place where it happens.
    assert() is exactly the tool designed for this: It terminates the
    program immediately, and with the aid of a debugger you can see the
    whole stack trace and the values of the variables exactly when the error
    happened. This way the programming error can be fixed, and the indexing
    out of boundaries will not happen anymore.

    I can't even begin to imagine why throwing an exception instead, and
    catching it somewhere else than right where the error happens, would be
    a better idea.

    The only advantage of throwing an exception is that the program could,
    if so designed (which is often *very* laborious), continue without
    interruption. However, what would the program do in that case? A bug has
    been detected, and now the program knows that function is flawed, the
    data is incorrect, and nothing that function returned can be relied on.
    That buggy function is completely useless. What exactly is the right
    course of action in this case? (And how does it differ from a simple
    assert?)
     
    Juha Nieminen, Mar 16, 2008
    #8
  9. Alexander Dong Back Kim

    red floyd Guest

    Juha Nieminen wrote:
    > Jeff Schwab wrote:
    >>> I can't think of many applications where at() throwing an exception
    >>> would be in any way a desirable thing. (As mentioned, to catch
    >>> programming errors IMO using assert() is better.)

    >> Huh? The exception is *exactly* the right solution, for the reasons red
    >> floyd already explained.

    >
    > Could you please explain to me why is that?
    >
    > If indexing out of boundaries at some place is an indication of a
    > programming error, ie. a bug, the best course of action is to report
    > immediately about this detected error, at the place where it happens.
    > assert() is exactly the tool designed for this: It terminates the
    > program immediately, and with the aid of a debugger you can see the
    > whole stack trace and the values of the variables exactly when the error
    > happened. This way the programming error can be fixed, and the indexing
    > out of boundaries will not happen anymore.
    >
    > I can't even begin to imagine why throwing an exception instead, and
    > catching it somewhere else than right where the error happens, would be
    > a better idea.
    >

    Because the correct place to catch the error is not in at(), or in
    GetApple(), but rather in the caller of GetApple(), who will have some
    sense of what to do with it.
     
    red floyd, Mar 17, 2008
    #9
  10. Alexander Dong Back Kim

    Kai-Uwe Bux Guest

    red floyd wrote:

    > Juha Nieminen wrote:
    >> Jeff Schwab wrote:
    >>>> I can't think of many applications where at() throwing an exception
    >>>> would be in any way a desirable thing. (As mentioned, to catch
    >>>> programming errors IMO using assert() is better.)
    >>> Huh? The exception is *exactly* the right solution, for the reasons red
    >>> floyd already explained.

    >>
    >> Could you please explain to me why is that?
    >>
    >> If indexing out of boundaries at some place is an indication of a
    >> programming error, ie. a bug, the best course of action is to report
    >> immediately about this detected error, at the place where it happens.
    >> assert() is exactly the tool designed for this: It terminates the
    >> program immediately, and with the aid of a debugger you can see the
    >> whole stack trace and the values of the variables exactly when the error
    >> happened. This way the programming error can be fixed, and the indexing
    >> out of boundaries will not happen anymore.
    >>
    >> I can't even begin to imagine why throwing an exception instead, and
    >> catching it somewhere else than right where the error happens, would be
    >> a better idea.
    >>

    > Because the correct place to catch the error is not in at(), or in
    > GetApple(), but rather in the caller of GetApple(), who will have some
    > sense of what to do with it.


    That very much depends. There are two cases:

    a) an out of bounds error indicates a bug in the program (i.e., something
    happened that the programmer did not expect). Then code in GetApple() is in
    no way better equipped to deal with the event. An assert() is the
    appropriate response.

    b) an out of bounds error does not indicate a bug (i.e., out of bound
    indices are permitted by design). In this case, an exception is appropriate
    if the condition might require stack unwinding for best handling.



    I have never seen a design where an out of bounds error of type (b) was a
    good idea.



    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Mar 17, 2008
    #10
  11. Alexander Dong Back Kim

    Jeff Schwab Guest

    Juha Nieminen wrote:
    > Jeff Schwab wrote:
    >>> I can't think of many applications where at() throwing an exception
    >>> would be in any way a desirable thing. (As mentioned, to catch
    >>> programming errors IMO using assert() is better.)

    >> Huh? The exception is *exactly* the right solution, for the reasons red
    >> floyd already explained.

    >
    > Could you please explain to me why is that?


    I think red floyd already explained it as well as I could.

    > If indexing out of boundaries at some place is an indication of a
    > programming error, ie. a bug, the best course of action is to report
    > immediately about this detected error, at the place where it happens.


    That may be the best place to for the error to be detected, but it's not
    necessarily the right place for it to be handled. In particular, part
    of the code you snipped showed that the index was originally passed to
    the OP's function from some client. The error is almost certainly in
    the client code, not the OP's class, so it is the client who needs to be
    notified. Maybe the client would like to log the error but keep the
    program running, or maybe the client would like to terminate the program
    altogether. This is the not for the OP's class to decide.

    > assert() is exactly the tool designed for this:


    Nope. Assert is for documenting that a particular condition is
    impossible. Assert is frequently abused to verify prerequisites, but an
    assertion failure really is, by definition, an internal error.

    > It terminates the program immediately,


    And that's what you want your client to see? Your library crashing the
    whole program?

    > and with the aid of a debugger


    Any plan to spend time in the debugger is a self-fulling prophecy.

    Anyway, you're missing the point: The bug isn't in the OP's code, it's
    in the client code, which he may not have, in which case he cannot run
    in his debugger.

    > you can see the
    > whole stack trace and the values of the variables exactly when the error
    > happened. This way the programming error can be fixed, and the indexing
    > out of boundaries will not happen anymore.


    By the time you see a stack trace, you're already working backwards.
    The best tools for finding and tracking logical errors are compilers and
    unit tests. It is uncanny how the people who are best with the debugger
    are the worst developers. (That's not meant as a dig at you, btw; I
    have no idea what your day-to-day code looks like, and I'm not in a
    position to criticize it.)

    Suppose you are using some library code, you pass it a bad value (we all
    make mistakes), and then at run-time you see (shiver) an assertion
    failure. The stack trace shows you where the error nominally occurred,
    and what the call-stack was at the time. You didn't write the functions
    at the top or the bottom of the stack trace, but you some of your own
    code somewhere in the middle; you therefore crank up the debugger (you
    poor, misguided soul) so that you can figure out where the root cause of
    the error is. Until you figure out where the bad value originated, you
    don't know whether or whither to direct your bug report. (You don't
    know that the real problem is anywhere near where the assertion error
    occurred, because the library is abusing assert() to serve as a prereq
    check.)

    To figure out where the error actually originated, you have to walk
    through the code (starting where?) in the debugger, step by step, over
    who knows how many LOC, until you see the assertion error
    .. Then you usually have to do it again, because you still haven't found
    the root cause, for the same reason you (or someone else) wrote
    incorrect code in the first place. Stepping through code takes O(N)
    time with the amount of code involved. It is quite possibly the single
    least efficient way of finding and fixing errors that is still in common
    use.

    > I can't even begin to imagine why throwing an exception instead, and
    > catching it somewhere else than right where the error happens, would be
    > a better idea.


    The error goes to whomever believes they can catch it.

    > The only advantage of throwing an exception is that the program could,
    > if so designed (which is often *very* laborious), continue without
    > interruption.


    But sometimes *very* [sic] necessary.

    > However, what would the program do in that case? A bug has
    > been detected,


    An exception does not necessarily indicate a bug. It may just indicate
    some input error, or other exceptional condition. (In the case of an
    index being passed down, I agree that the index probably should have
    been validated before an exception became necessary.)

    > and now the program knows that function is flawed, the
    > data is incorrect, and nothing that function returned can be relied on.


    For better or worse, sometimes it has to. Suppose a plane's on-board
    GPS software encounters an error. Should the whole on-board computer
    just give up and let the plane drop from the sky? Of course not; it
    should report to the error that the GPS is wonky, but do the best it can
    to keep the plane in the air. This example is probably more extreme
    than the OP's AppleCart, but the principle is the same. Once, while I
    was working for a server company, our manager was very proud of our
    product's nine-minute fail-over time. We then found out it wasn't good
    enough, and I was cranky -- "What do they expect from us?" -- until I
    found out that the servers were being used to route calls at an
    emergency response center. Nine minutes are a long time to wait when
    your child is choking on something. A crash is sometimes just not an
    option, and post-mortem debug would not have been enough.

    Client code seeing an assertion failure is a Very Bad Thing, even if no
    one actually plummets to their death as a result. Even if the client
    does something wrong (again: We all make mistakes), the least your
    library can do is give them a chance to handle the exception.

    > That buggy function is completely useless.


    You don't know that.

    > What exactly is the right course of action in this case?


    Only the caller knows.

    > (And how does it differ from a simple assert?)


    It gives the application an opportunity to handle the exception, as
    opposed to aborting the program.
     
    Jeff Schwab, Mar 17, 2008
    #11
  12. Alexander Dong Back Kim

    Kai-Uwe Bux Guest

    Jeff Schwab wrote:

    > Juha Nieminen wrote:
    >> Jeff Schwab wrote:
    >>>> I can't think of many applications where at() throwing an exception
    >>>> would be in any way a desirable thing. (As mentioned, to catch
    >>>> programming errors IMO using assert() is better.)
    >>> Huh? The exception is *exactly* the right solution, for the reasons red
    >>> floyd already explained.

    >>
    >> Could you please explain to me why is that?

    >
    > I think red floyd already explained it as well as I could.
    >
    >> If indexing out of boundaries at some place is an indication of a
    >> programming error, ie. a bug, the best course of action is to report
    >> immediately about this detected error, at the place where it happens.

    >
    > That may be the best place to for the error to be detected, but it's not
    > necessarily the right place for it to be handled. In particular, part
    > of the code you snipped showed that the index was originally passed to
    > the OP's function from some client. The error is almost certainly in
    > the client code, not the OP's class, so it is the client who needs to be
    > notified. Maybe the client would like to log the error but keep the
    > program running, or maybe the client would like to terminate the program
    > altogether. This is the not for the OP's class to decide.


    It is for the OP to decide what the invariants of the class are and what the
    contracts for its member functions should be. Once the contract is
    published, it is the client code programmers task to deal with that. (Of
    course, in a larger project, client code programmers might have particular
    requests about how they would like the contracts to be worded.)

    If the contract states that any input shall be accepted but certain inputs
    be reported by an exception, so be it. If the contract states that certain
    inputs are invalid and lead to undefined behavior, an assert() is the right
    choice.

    >> assert() is exactly the tool designed for this:

    >
    > Nope. Assert is for documenting that a particular condition is
    > impossible.


    You probably mean "unforseen". Impossible conditions could not happen.


    > Assert is frequently abused to verify prerequisites, but an
    > assertion failure really is, by definition, an internal error.


    Assertions can be used to verify preconditions, i.e., to enforce the
    contract of a routine. By definition, a violation of the contract does not
    entitle the violating party to anything. In particular, there is no
    requirement that the caller be notified.

    Or, to say the same thing the other way around: if the caller is to be
    notified by an exception, the input was not in violation of the contract
    but the contract required a throw of an exception.


    [snip]


    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Mar 17, 2008
    #12
  13. Alexander Dong Back Kim

    Jeff Schwab Guest

    Kai-Uwe Bux wrote:
    > Jeff Schwab wrote:
    >
    >> Juha Nieminen wrote:
    >>> Jeff Schwab wrote:
    >>>>> I can't think of many applications where at() throwing an exception
    >>>>> would be in any way a desirable thing. (As mentioned, to catch
    >>>>> programming errors IMO using assert() is better.)
    >>>> Huh? The exception is *exactly* the right solution, for the reasons red
    >>>> floyd already explained.
    >>> Could you please explain to me why is that?

    >> I think red floyd already explained it as well as I could.
    >>
    >>> If indexing out of boundaries at some place is an indication of a
    >>> programming error, ie. a bug, the best course of action is to report
    >>> immediately about this detected error, at the place where it happens.

    >> That may be the best place to for the error to be detected, but it's not
    >> necessarily the right place for it to be handled. In particular, part
    >> of the code you snipped showed that the index was originally passed to
    >> the OP's function from some client. The error is almost certainly in
    >> the client code, not the OP's class, so it is the client who needs to be
    >> notified. Maybe the client would like to log the error but keep the
    >> program running, or maybe the client would like to terminate the program
    >> altogether. This is the not for the OP's class to decide.

    >
    > It is for the OP to decide what the invariants of the class are and what the
    > contracts for its member functions should be. Once the contract is
    > published, it is the client code programmers task to deal with that. (Of
    > course, in a larger project, client code programmers might have particular
    > requests about how they would like the contracts to be worded.)
    >
    > If the contract states that any input shall be accepted but certain inputs
    > be reported by an exception, so be it. If the contract states that certain
    > inputs are invalid and lead to undefined behavior, an assert() is the right
    > choice.


    I have seen that view espoused before, and I disagree with it. Even if
    crashing the program is deemed the best option, assert is exactly the
    wrong way to achieve that end.

    >>> assert() is exactly the tool designed for this:

    >> Nope. Assert is for documenting that a particular condition is
    >> impossible.

    >
    > You probably mean "unforseen".


    No, I mean "impossible." There is, again by definition, no way to
    prepare for an unforeseen event. To the extent that you are preparing
    for something, it is not unforeseen.

    > Impossible conditions could not happen.


    Which is why assertions should never fail. If an assertion does fail,
    then the condition was not impossible after all, and there is a bug in
    the program.

    >> Assert is frequently abused to verify prerequisites, but an
    >> assertion failure really is, by definition, an internal error.

    >
    > Assertions can be used to verify preconditions, i.e., to enforce the
    > contract of a routine.


    "Can" and "should" are two different things.

    > By definition, a violation of the contract does not
    > entitle the violating party to anything. In particular, there is no
    > requirement that the caller be notified.


    If that is your philosophy, then why validate your input parameters at
    all? There is valid code designed this way, but if you are bothering to
    check the validity of your input, you can at least handle any errors as
    gracefully as possible.

    > Or, to say the same thing the other way around: if the caller is to be
    > notified by an exception, the input was not in violation of the contract
    > but the contract required a throw of an exception.


    If the contract requires an exception, then an exception must be thrown;
    however, a contract violation that is not guaranteed to throw an
    exception may throw one anyway, unless a specific no-throw guarantee is
    in place (as is common for destructors).
     
    Jeff Schwab, Mar 17, 2008
    #13
  14. Alexander Dong Back Kim

    Kai-Uwe Bux Guest

    Jeff Schwab wrote:

    > Kai-Uwe Bux wrote:
    >> Jeff Schwab wrote:
    >>
    >>> Juha Nieminen wrote:
    >>>> Jeff Schwab wrote:
    >>>>>> I can't think of many applications where at() throwing an exception
    >>>>>> would be in any way a desirable thing. (As mentioned, to catch
    >>>>>> programming errors IMO using assert() is better.)
    >>>>> Huh? The exception is *exactly* the right solution, for the reasons
    >>>>> red floyd already explained.
    >>>> Could you please explain to me why is that?
    >>> I think red floyd already explained it as well as I could.
    >>>
    >>>> If indexing out of boundaries at some place is an indication of a
    >>>> programming error, ie. a bug, the best course of action is to report
    >>>> immediately about this detected error, at the place where it happens.
    >>> That may be the best place to for the error to be detected, but it's not
    >>> necessarily the right place for it to be handled. In particular, part
    >>> of the code you snipped showed that the index was originally passed to
    >>> the OP's function from some client. The error is almost certainly in
    >>> the client code, not the OP's class, so it is the client who needs to be
    >>> notified. Maybe the client would like to log the error but keep the
    >>> program running, or maybe the client would like to terminate the program
    >>> altogether. This is the not for the OP's class to decide.

    >>
    >> It is for the OP to decide what the invariants of the class are and what
    >> the contracts for its member functions should be. Once the contract is
    >> published, it is the client code programmers task to deal with that. (Of
    >> course, in a larger project, client code programmers might have
    >> particular requests about how they would like the contracts to be
    >> worded.)
    >>
    >> If the contract states that any input shall be accepted but certain
    >> inputs be reported by an exception, so be it. If the contract states that
    >> certain inputs are invalid and lead to undefined behavior, an assert() is
    >> the right choice.

    >
    > I have seen that view espoused before, and I disagree with it. Even if
    > crashing the program is deemed the best option, assert is exactly the
    > wrong way to achieve that end.
    >
    >>>> assert() is exactly the tool designed for this:
    >>> Nope. Assert is for documenting that a particular condition is
    >>> impossible.

    >>
    >> You probably mean "unforseen".

    >
    > No, I mean "impossible." There is, again by definition, no way to
    > prepare for an unforeseen event. To the extent that you are preparing
    > for something, it is not unforeseen.
    >
    >> Impossible conditions could not happen.

    >
    > Which is why assertions should never fail. If an assertion does fail,
    > then the condition was not impossible after all, and there is a bug in
    > the program.


    That is why I would say "unforseen". If an assertion fails it proves that I
    failed to see that the case could happen. I put the assertion documenting
    by believe that a certain path of execution would never be taken, but I do
    so because I know I might be wrong.

    But we agree on the substance: an assert() claims that a certain condition
    is true and when it turns out to be false, there is a bug.


    >>> Assert is frequently abused to verify prerequisites, but an
    >>> assertion failure really is, by definition, an internal error.

    >>
    >> Assertions can be used to verify preconditions, i.e., to enforce the
    >> contract of a routine.

    >
    > "Can" and "should" are two different things.
    >
    >> By definition, a violation of the contract does not
    >> entitle the violating party to anything. In particular, there is no
    >> requirement that the caller be notified.

    >
    > If that is your philosophy, then why validate your input parameters at
    > all? There is valid code designed this way, but if you are bothering to
    > check the validity of your input, you can at least handle any errors as
    > gracefully as possible.


    I claim that for contracts that specify undefined behavior, an assertion is
    more often than not the most graceful way of handling a violation:

    a) The assertion can be eliminated in performance critical regions when the
    code is considered program is considered debugged.

    b) Aborting the program when a bug is encountered is often just the
    RightThing(tm). If the program goes on although a bug has been detected,
    the output cannot be trusted, which is often fatal. I really appreciate
    when my compiler fails with an Internal Compiler Error to the compiler
    producing bogus object code. I do see that there are classes of bugs that
    can be handled differently: e.g., rendering bugs in games, where the
    problem will go away after a few frames and aborting the game would
    definitely make for a worse gaming experience. Whether an abort is graceful
    or not is strongly related to whether and how correctness of output is
    defined and how much it matters.

    c) The contract does not specify which exception would be thrown. So what
    should the caller catch?


    >> Or, to say the same thing the other way around: if the caller is to be
    >> notified by an exception, the input was not in violation of the contract
    >> but the contract required a throw of an exception.

    >
    > If the contract requires an exception, then an exception must be thrown;
    > however, a contract violation that is not guaranteed to throw an
    > exception may throw one anyway, unless a specific no-throw guarantee is
    > in place (as is common for destructors).


    Any exception that is thrown _should_ specified in the contract. Otherwise,
    why should a caller provide a catch() clause? Uncaught exceptions are more
    or less equivalent to asserts in that they unwinde the stack completely.


    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Mar 17, 2008
    #14
  15. Alexander Dong Back Kim

    James Kanze Guest

    On Mar 14, 6:22 pm, Jeff Schwab <> wrote:
    > Juha Nieminen wrote:
    > > Alexander Dong Back Kim wrote:
    > >> try
    > >> {
    > >> return _appleBox.at(index);
    > >> }
    > >> catch (out_of_range e)
    > >> {
    > >> return ???;
    > >> }


    > > Perhaps a different design could be better here?


    > > Usually indexing out of boundaries means one of two things:


    > > 1) It's an error, ie. a bug in the code. In this case an
    > > assert() is usually better than throwing (because you can
    > > get the whole call stack easily with a debugger).


    > <gasp> Strongly disagree. </>


    Huh? You have code which you've just proven doesn't work, and
    you want it to continue doing incorrectly whatever it was doing?

    When you detect an "impossible" state in the code, the only
    correct thing to do, nine times out of ten, is to abort the
    program as soon as possible, rather than continue stumbling on,
    without really knowing whether the results are correct or not.
    (This obviously depends somewhat on the domain. In process
    control, and especially with critical systems, not aborting
    would almost amount to criminal negligence. At the other
    extreme, in games programs, the worst thing that could happen if
    you don't abort is that the program crashes, which comes out to
    about the same, so aborting is probably wrong, at least in
    released code. Most programs, however, are probably closer to
    the first situation---they do something whose results matter,
    and no results are better than incorrect results.)

    [...]
    > > I can't think of many applications where at() throwing an
    > > exception would be in any way a desirable thing. (As
    > > mentioned, to catch programming errors IMO using assert() is
    > > better.)


    > Huh? The exception is *exactly* the right solution, for the
    > reasons red floyd already explained.


    If you've detected a situation which can only be the result of a
    programming error, i.e. if you've detected that some pre- or
    post-condition or some invariant doesn't hold, then you can have
    no confidence in whatever the program does from then on. In
    such cases, the correct procedure is almost always to abort, so
    that higher level corrective action can occur.

    --
    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, Mar 17, 2008
    #15
  16. Alexander Dong Back Kim

    James Kanze Guest

    On Mar 17, 12:51 am, Juha Nieminen <> wrote:
    > Jeff Schwab wrote:
    > >> I can't think of many applications where at() throwing an exception
    > >> would be in any way a desirable thing. (As mentioned, to catch
    > >> programming errors IMO using assert() is better.)


    > > Huh? The exception is *exactly* the right solution, for the
    > > reasons red floyd already explained.


    > Could you please explain to me why is that?


    > If indexing out of boundaries at some place is an indication
    > of a programming error, ie. a bug, the best course of action
    > is to report immediately about this detected error, at the
    > place where it happens. assert() is exactly the tool designed
    > for this: It terminates the program immediately, and with the
    > aid of a debugger you can see the whole stack trace and the
    > values of the variables exactly when the error happened. This
    > way the programming error can be fixed, and the indexing out
    > of boundaries will not happen anymore.


    Note that even without the possibilities of a debugger...

    [...]
    > The only advantage of throwing an exception is that the
    > program could, if so designed (which is often *very*
    > laborious), continue without interruption. However, what would
    > the program do in that case? A bug has been detected, and now
    > the program knows that function is flawed, the data is
    > incorrect, and nothing that function returned can be relied
    > on. That buggy function is completely useless. What exactly
    > is the right course of action in this case? (And how does it
    > differ from a simple assert?)


    That's the key point. If you can't count on doing anything
    correct, the only course of action is not doing anything,
    quickly and noisily, so that whatever back up systems are
    available can take over. (The "back up system" might be as
    simple as a human being deciding that we'll have to do without
    that functionality for the moment.)

    --
    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, Mar 17, 2008
    #16
  17. Alexander Dong Back Kim

    James Kanze Guest

    On Mar 17, 2:23 am, red floyd <> wrote:
    > Juha Nieminen wrote:
    > > Jeff Schwab wrote:
    > >>> I can't think of many applications where at() throwing an exception
    > >>> would be in any way a desirable thing. (As mentioned, to catch
    > >>> programming errors IMO using assert() is better.)
    > >> Huh? The exception is *exactly* the right solution, for the reasons red
    > >> floyd already explained.


    > > Could you please explain to me why is that?


    > > If indexing out of boundaries at some place is an indication of a
    > > programming error, ie. a bug, the best course of action is to report
    > > immediately about this detected error, at the place where it happens.
    > > assert() is exactly the tool designed for this: It terminates the
    > > program immediately, and with the aid of a debugger you can see the
    > > whole stack trace and the values of the variables exactly when the error
    > > happened. This way the programming error can be fixed, and the indexing
    > > out of boundaries will not happen anymore.


    > > I can't even begin to imagine why throwing an exception instead, and
    > > catching it somewhere else than right where the error happens, would be
    > > a better idea.


    > Because the correct place to catch the error is not in at(),
    > or in GetApple(), but rather in the caller of GetApple(), who
    > will have some sense of what to do with it.


    And how will the caller of GetApple() have some sense of what to
    do with it? If the argument is the result of a programming
    error, and you can't logically isolate the error (and if there
    is a programming error, it means that your reasoning about the
    program was wrong, so you can't logically say anything about the
    program), then there is no place in the code where you can have
    some sense of what to do with the error. The only thing to do
    is to "propagate" the "exception" somewhere outside of the
    corrupted process. Which is really what an assertion failure
    does: it is an "exception" which can only be caught and handled
    outside the process. (Outside the process, of course, might
    even be outside the machine, e.g. a human operator.)

    --
    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, Mar 17, 2008
    #17
  18. Alexander Dong Back Kim

    James Kanze Guest

    On Mar 17, 3:22 am, Jeff Schwab <> wrote:
    > Juha Nieminen wrote:
    > > Jeff Schwab wrote:
    > >>> I can't think of many applications where at() throwing an exception
    > >>> would be in any way a desirable thing. (As mentioned, to catch
    > >>> programming errors IMO using assert() is better.)
    > >> Huh? The exception is *exactly* the right solution, for the reasons red
    > >> floyd already explained.


    > > Could you please explain to me why is that?


    > I think red floyd already explained it as well as I could.


    I didn't see where he explained anything except how an exception
    works.

    > > If indexing out of boundaries at some place is an indication of a
    > > programming error, ie. a bug, the best course of action is to report
    > > immediately about this detected error, at the place where it happens.


    > That may be the best place to for the error to be detected,
    > but it's not necessarily the right place for it to be handled.


    That's not what he said. He said it's the best place to report
    the error. Where you have a complete stack trace and a maximum
    of other information. Anything you do after detecting the error
    may loose information or degrade the situation.

    > In particular, part of the code you snipped showed that the
    > index was originally passed to the OP's function from some
    > client. The error is almost certainly in the client code, not
    > the OP's class, so it is the client who needs to be notified.


    Let's see if I've got this right. The client code is hosed, to
    the point of provenly being incapable of even providing a
    correct argument, and you're saying that it's the most
    trustworthy place for the error to be handled. There's
    something that I don't understand there. The exception *must*
    propagate at least beyond the client code which was corrupted.
    Without executing any code in the corrupted client. Including
    destructors.

    That's sounds like abort, to me. It's certainly not exceptions.

    > Maybe the client would like to log the error but keep the
    > program running, or maybe the client would like to terminate
    > the program altogether. This is the not for the OP's class to
    > decide.


    The client has proven himself incapable of deciding. Someone
    has to decide. By aborting, you push the decision up to a
    higher level.

    > > assert() is exactly the tool designed for this:


    > Nope. Assert is for documenting that a particular condition
    > is impossible.


    Exactly. And the impossible has just happened. So all bets are
    off.

    > Assert is frequently abused to verify prerequisites, but an
    > assertion failure really is, by definition, an internal error.


    And calling a function while failing to meet the preconditions
    isn't an interal error?

    > > It terminates the program immediately,


    > And that's what you want your client to see? Your library
    > crashing the whole program?


    Better that, than silently giving a wrong results. Maybe
    causing the rods to be pulled out of the reactor, and resulting
    in a nuclear meltdown. (My view of this may be prejudiced
    because I've worked on critical systems in the past. I
    particularly remember the locomotive brake system, where the
    emergency brake system which was used when our system detected
    an error actually cut all power to the processor. They weren't
    taking any chances of our doing something wrong.)

    > > and with the aid of a debugger


    > Any plan to spend time in the debugger is a self-fulling prophecy.


    > Anyway, you're missing the point: The bug isn't in the OP's
    > code, it's in the client code, which he may not have, in which
    > case he cannot run in his debugger.


    I think you're missing the point. The error is somewhere in the
    process. We don't know where, but we can no longer count on the
    process doing the right thing.

    > > you can see the whole stack trace and the values of the
    > > variables exactly when the error happened. This way the
    > > programming error can be fixed, and the indexing out of
    > > boundaries will not happen anymore.


    > By the time you see a stack trace, you're already working
    > backwards. The best tools for finding and tracking logical
    > errors are compilers and unit tests. It is uncanny how the
    > people who are best with the debugger are the worst
    > developers. (That's not meant as a dig at you, btw; I have no
    > idea what your day-to-day code looks like, and I'm not in a
    > position to criticize it.)


    Debuggers are useful for post-mortems. A stack trace. That's
    about it, but that's still something. (That's not strictly
    true. I actually had a case the other day where I found the
    debugger was really useful on running code. First time in about
    twenty years.)

    I think you're putting too much emphisis on the debugger part.
    The important aspect is that if you couldn't count on the client
    code giving you a correct argument, how can you count on it
    doing correct error handling.

    > Suppose you are using some library code, you pass it a bad
    > value (we all make mistakes), and then at run-time you see
    > (shiver) an assertion failure. The stack trace shows you
    > where the error nominally occurred, and what the call-stack
    > was at the time. You didn't write the functions at the top or
    > the bottom of the stack trace, but you some of your own code
    > somewhere in the middle; you therefore crank up the debugger
    > (you poor, misguided soul) so that you can figure out where
    > the root cause of the error is. Until you figure out where
    > the bad value originated, you don't know whether or whither to
    > direct your bug report. (You don't know that the real problem
    > is anywhere near where the assertion error occurred, because
    > the library is abusing assert() to serve as a prereq check.)


    That's a fact of life. I've had to handle assertion failures
    which were ultimately due to an uninitialized pointer in some
    totally unrelated code. The clients data were completely hosed.

    > To figure out where the error actually originated, you have to
    > walk through the code (starting where?) in the debugger, step
    > by step, over who knows how many LOC, until you see the
    > assertion error.


    No. You start by reasoning about the error. And by going to
    the log, and seeing what happend before. If the error is caused
    by data corruption (all too often the case), you then try and
    reproduce it. Until you can reproduce it, you can't fix it.

    Generally, once I've determined the cause of the error, from the
    stack walkback, I don't use the debugger any more. But that's
    really not the issue. The point I think Juha was making is that
    if the client code catches the exception, and masks it, you
    can't even determine what the cause was, so you don't really
    have the information necessary to begin trying to reproduce it.
    In the worst case, the error disappears completely, the program
    outputs a wrong result, and nobody is even aware of it.

    > Then you usually have to do it again, because you still
    > haven't found the root cause, for the same reason you (or
    > someone else) wrote incorrect code in the first place.
    > Stepping through code takes O(N) time with the amount of code
    > involved. It is quite possibly the single least efficient way
    > of finding and fixing errors that is still in common use.


    It's true that just ignoring them, and using the wrong results,
    requires less effort on the part of the developers.

    > > I can't even begin to imagine why throwing an exception
    > > instead, and catching it somewhere else than right where the
    > > error happens, would be a better idea.


    > The error goes to whomever believes they can catch it.


    And you trust them, given that they're also the ones who
    provided the wrong argument in the first place.

    > > The only advantage of throwing an exception is that the
    > > program could, if so designed (which is often *very*
    > > laborious), continue without interruption.


    > But sometimes *very* [sic] necessary.


    Usually, such aspects are handled as a system level, outside of
    the process. (At least, I've never seen a system in industry
    where they weren't, and the same thing has held for all of the
    server software in the commercial applications I've seen. About
    the only exception to this rule has been light weight GUI front
    ends, which don't calculate or decide anything, but just
    display.)

    > > However, what would the program do in that case? A bug has
    > > been detected,


    > An exception does not necessarily indicate a bug.


    It shouldn't ever indicate a programming error. That's not its
    role.

    > It may just indicate some input error, or other exceptional
    > condition. (In the case of an index being passed down, I
    > agree that the index probably should have been validated
    > before an exception became necessary.)


    Which is all Juta is saying. It's hard to imagine a case where
    an exception is the desired behavior for an array bounds error.

    > > and now the program knows that function is flawed, the data
    > > is incorrect, and nothing that function returned can be
    > > relied on.


    > For better or worse, sometimes it has to. Suppose a plane's
    > on-board GPS software encounters an error. Should the whole
    > on-board computer just give up and let the plane drop from the
    > sky?


    The whole on-board computer should just give up, noisily, so
    that the backup system can take over, and so that in the worst
    case, the pilot knows that he cannot count on it, and resorts to
    some alternative. This is much preferable to a system which
    informs the pilot that he has 1000 ft altitude, and should
    descend 500 ft in the landing approach, when he's really only
    200 ft above the ground.

    > Of course not; it should report to the error that the GPS is
    > wonky, but do the best it can to keep the plane in the air.


    Have you ever actually worked on such systems? In the end, it's
    the pilot's responsibility to keep the plane in the air, and
    anytime the software isn't sure of doing the right thing, it
    should abort, letting the backup systems take over (where the
    ultimate backup system is the pilot). In such cases, giving
    wrong information or doing the wrong thing is worse than giving
    no information or doing nothing.

    > This example is probably more extreme than the OP's AppleCart,
    > but the principle is the same. Once, while I was working for
    > a server company, our manager was very proud of our product's
    > nine-minute fail-over time. We then found out it wasn't good
    > enough, and I was cranky -- "What do they expect from us?" --
    > until I found out that the servers were being used to route
    > calls at an emergency response center. Nine minutes are a
    > long time to wait when your child is choking on something. A
    > crash is sometimes just not an option, and post-mortem debug
    > would not have been enough.


    Many of the systems I've worked on in the past have had
    contractual penalties for down time. It's fairly usual
    procedure in many fields.

    > Client code seeing an assertion failure is a Very Bad Thing,
    > even if no one actually plummets to their death as a result.


    Not seeing an assertion failure when the program is wrong is an
    almost sure guarantee of the plane doing something wrong.

    > Even if the client does something wrong (again: We all make
    > mistakes), the least your library can do is give them a chance
    > to handle the exception.


    > > That buggy function is completely useless.


    > You don't know that.


    You don't know anything about it. You can't take chances.

    > > What exactly is the right course of action in this case?


    > Only the caller knows.


    You do know that the caller isn't behaving correctly. How can
    you count on him doing the right thing in terms of error
    recovery, when he wasn't capable of doing the right thing when
    he passed you the arguments? Has he somehow, miraculously,
    fixed himself.

    > > (And how does it differ from a simple assert?)

    >
    > It gives the application an opportunity to handle the exception, as
    > opposed to aborting the program.


    The error must be propagated up to a point outside of the
    process. That's the only place where there's a reasonable
    chance of it being handled correctly. (Note that most systems
    or applications---and all critical systems and
    applications---consist of more than a single program.)

    --
    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, Mar 17, 2008
    #18
  19. I couldn't have responded better than James did. One note, though:

    > On Mar 17, 3:22 am, Jeff Schwab <> wrote:
    >> By the time you see a stack trace, you're already working
    >> backwards. The best tools for finding and tracking logical
    >> errors are compilers and unit tests. It is uncanny how the
    >> people who are best with the debugger are the worst
    >> developers. (That's not meant as a dig at you, btw; I have no
    >> idea what your day-to-day code looks like, and I'm not in a
    >> position to criticize it.)


    I honestly can't understand this opinion.

    Developers are humans, and humans make mistakes. No matter how
    experienced you are at developing, even if you are the best C++
    developer in the world and your code has the best quality in the world,
    you will make small mistakes here and there from time to time.

    The vast majority of these small mistakes can be found with a proper
    debugger almost immediately. You simply have to see the line where the
    program crashed in order to immediately see your own mistake and fix it.
    Without the aid of a debugger it could take tens of minutes, or even
    hours at worst. ("Segmentation fault" is not a very informative error
    message. Having to find the place where the fault happens by adding
    debugging prints to your program can be a real pain.)

    If the error is not exactly at the line where the crash happened, the
    debugger is even more useful, exactly because of the stack trace. You
    can navigate the call stack down until you find the actual place where
    the error happened, you can easily examine the values of the variables
    at that place, and in the majority of the cases you will immediately see
    what the problem was (usually a small typo or thought mistake).

    It is, of course, possible to have really nasty bugs which are
    extremely hard, or even impossible, to find with just a debugger.
    However, that doesn't mean that the debugger isn't useful.

    If I had to develop C++ programs without any kind of debugger, it
    would be a real pain. Each small mistake, each small typo, would require
    a long and laborious task of manually adding debug prints to try to
    binary-search the location of the error... Horrible.
    (I have actually had to do this in the past, when developing programs
    in a Unix environment using gcc and without gdb or any other kind of
    debugger. It was not nice.)
     
    Juha Nieminen, Mar 17, 2008
    #19
  20. Alexander Dong Back Kim

    Ian Collins Guest

    Juha Nieminen wrote:
    >
    > If I had to develop C++ programs without any kind of debugger, it
    > would be a real pain. Each small mistake, each small typo, would require
    > a long and laborious task of manually adding debug prints to try to
    > binary-search the location of the error... Horrible.


    There is a school of thought that I am becoming more aligned with as my
    TDD skills improve that says using a debugger on new code is a sign
    flaws in your development process.

    I try avoid the debugger wherever possible, it simply slows me down.
    Better to make a small change, run the tests. If a test fails, revert
    the change and do it again another way. Debugging with a debugger is
    one of those intense processes that can suck up a lot of time before you
    realise ad it disrupts the development flow.

    I started working this way while building a complex PHP application, I
    never did find a decent PHP debugger, so I became a much more
    accomplished test writer.

    --
    Ian Collins.
     
    Ian Collins, Mar 17, 2008
    #20
    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. BCC
    Replies:
    12
    Views:
    844
    Clark Cox
    Feb 6, 2004
  2. pmatos
    Replies:
    6
    Views:
    24,022
  3. Replies:
    8
    Views:
    1,984
    Csaba
    Feb 18, 2006
  4. Javier
    Replies:
    2
    Views:
    601
    James Kanze
    Sep 4, 2007
  5. Rushikesh Joshi
    Replies:
    0
    Views:
    386
    Rushikesh Joshi
    Jul 10, 2004
Loading...

Share This Page