Use of Assertions

Discussion in 'C++' started by Divick, Feb 15, 2006.

  1. Divick

    Divick Guest

    Hi,
    is it a nice idea to do assetion checks for method arguments ? I
    am currently redesigning a piece of code. Now the problem is that there
    are some assumptions for the method arguments that the code makes. It
    is not checking the validity of the arguments everywhere because that
    would lead to performance penalty. So I am think that at least
    assertions will be able check the arguments at least for debug version
    to verify the design. But now it means that I put the assertions
    everywhere in the code, something like below:

    Code with out checks

    func1(Ptr1 * ptr1, Ptr2 * ptr2)
    {
    ptr2->do something...
    ptr1->call some method(ptr2);
    }

    Code with assertions
    func1(Ptr1 * ptr1, Ptr2 * ptr2)
    {
    assert( ptr1!= NULL && ptr2 != NULL); // And do this for all
    functions with arguments everywhere
    ptr2->do something...
    ptr1->call some method(ptr2);
    }

    so my questions really is : Is it a good idea to put the assertions for
    the function arguments like shown above? Why or why not?

    Thanks,
    Divick
     
    Divick, Feb 15, 2006
    #1
    1. Advertising

  2. Divick wrote:
    > Hi,
    > is it a nice idea to do assetion checks for method arguments ? I


    YES.

    ....
    > }
    >
    > Code with assertions
    > func1(Ptr1 * ptr1, Ptr2 * ptr2)
    > {
    > assert( ptr1!= NULL && ptr2 != NULL); // And do this for all


    assert( ptr1 )
    assert( ptr2 )

    Validate *each* argument rather than have one long expression.

    NULL *is* 0 is C++. I don't use NULL any more (personal preference).


    > functions with arguments everywhere
    > ptr2->do something...
    > ptr1->call some method(ptr2);
    > }
    >
    > so my questions really is : Is it a good idea to put the assertions for
    > the function arguments like shown above? Why or why not?


    It's a good idea because:

    a) It documents your assumptions and enforces them (at least in debug).
    b) It catches errors early (which is always desirable).
     
    Gianni Mariani, Feb 15, 2006
    #2
    1. Advertising

  3. * Divick:
    > Hi,
    > is it a nice idea to do assetion checks for method arguments ? I
    > am currently redesigning a piece of code. Now the problem is that there
    > are some assumptions for the method arguments that the code makes. It
    > is not checking the validity of the arguments everywhere because that
    > would lead to performance penalty. So I am think that at least
    > assertions will be able check the arguments at least for debug version
    > to verify the design. But now it means that I put the assertions
    > everywhere in the code, something like below:
    >
    > Code with out checks
    >
    > func1(Ptr1 * ptr1, Ptr2 * ptr2)
    > {
    > ptr2->do something...
    > ptr1->call some method(ptr2);
    > }
    >
    > Code with assertions
    > func1(Ptr1 * ptr1, Ptr2 * ptr2)
    > {
    > assert( ptr1!= NULL && ptr2 != NULL); // And do this for all
    > functions with arguments everywhere
    > ptr2->do something...
    > ptr1->call some method(ptr2);
    > }
    >
    > so my questions really is : Is it a good idea to put the assertions for
    > the function arguments like shown above?


    No.


    > Why or why not?


    Use reference arguments where you don't intend to support NULL-values.


    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Feb 15, 2006
    #3
  4. Divick

    Ben Pope Guest

    Divick wrote:
    > Hi,
    > is it a nice idea to do assetion checks for method arguments ? I
    > am currently redesigning a piece of code. Now the problem is that there
    > are some assumptions for the method arguments that the code makes. It
    > is not checking the validity of the arguments everywhere because that
    > would lead to performance penalty.


    1st priority: Correctness.
    2nd priority: Correctness!

    Much lower priority: Performance.

    Always validate the arguments, if there IS a performance penalty convert
    the ones that matter to assertions.

    If the input comes from the user, or a file or something, then
    assertions are not really a suitable option. Validate those things ASAP
    to contain the problem.

    Ben Pope
    --
    I'm not just a number. To many, I'm known as a string...
     
    Ben Pope, Feb 15, 2006
    #4
  5. Divick

    Divick Guest

    >>Use reference arguments where you don't intend to support NULL-values.
    Could you please give an example?

    Seems like people have different opinions about this. Confused...:(

    Divick
     
    Divick, Feb 15, 2006
    #5
  6. Hi Divick

    >>>Use reference arguments where you don't intend to support NULL-values.

    > Could you please give an example?
    >
    > Seems like people have different opinions about this. Confused...:(


    I do not think many people have different opinions on this. :)

    Those who said that you should use assertions to make sure
    your pointer parameters are not 0 were assuming you had a
    reason for using pointers in the first place. What Alf said was
    that you the question of whether to use assertions for this should
    not be an issue if you do not need pointers here but can use
    references.

    In other words....
    1. use assertions where needed.
    2. use references instead of pointers wherever possible.

    Just my two cents worth... and I hope it helps...

    Best regards,
    Jurko Gospodnetic
     
    Jurko Gospodnetic, Feb 15, 2006
    #6
  7. Divick

    Divick Guest

    >>Those who said that you should use assertions to make sure
    >>your pointer parameters are not 0 were assuming you had a
    >>reason for using pointers in the first place. What Alf said was
    >>that you the question of whether to use assertions for this should
    >>not be an issue if you do not need pointers here but can use
    >>references.

    Ok, that helps. Now I understand what Alf was trying to say.

    Thanks a lot,
    Divick
     
    Divick, Feb 15, 2006
    #7
  8. Jacek Dziedzic, Feb 16, 2006
    #8
  9. Divick wrote:
    > Hi,
    > is it a nice idea to do assetion checks for method arguments ?


    Yes! Better safe than sorry.

    If you are worried about performance (better support this
    with an actual time-test, rather than thinking "this could
    be too slow"), you might have two styles of asserts, like

    Assert(...)
    and
    CostlyAssert(...)

    that would be turned on/off independently with preprocessor
    stuff like

    #define WANT_ASSERTS
    #define WANT_COSTLYASSERTS

    Then you could leave Asserts on for both debug and release
    versions and turn CostlyAsserts only for debugging.

    HTH,
    - J.
     
    Jacek Dziedzic, Feb 16, 2006
    #9
  10. Jacek Dziedzic wrote:
    > Gianni Mariani wrote:
    >
    >>
    >> NULL *is* 0 is C++. I don't use NULL any more (personal preference).
    >>

    >
    > Yes, but what about problems like that which was discussed
    > recently:
    >
    > http://groups.google.com/group/comp...p:comp.lang.c++&rnum=1&hl=en#0c93d210e3c2b5cb


    That's a gem.

    Yes, function overloading with templates and the special meaning of
    literal 0 gets "overloaded".

    It's too late now, but I think the language rules around the 0 literal
    and null pointers to now be a bad idea. The NULL macro provides no help
    here from a readability perspective, so I think that's a bad idea as
    well (IMHO).
     
    Gianni Mariani, Feb 16, 2006
    #10
  11. Divick

    Greg Guest

    Divick wrote:
    > Hi,
    > is it a nice idea to do assetion checks for method arguments ? I
    > am currently redesigning a piece of code. Now the problem is that there
    > are some assumptions for the method arguments that the code makes. It
    > is not checking the validity of the arguments everywhere because that
    > would lead to performance penalty. So I am think that at least
    > assertions will be able check the arguments at least for debug version
    > to verify the design. But now it means that I put the assertions
    > everywhere in the code, something like below:
    >
    > Code with out checks
    >
    > func1(Ptr1 * ptr1, Ptr2 * ptr2)
    > {
    > ptr2->do something...
    > ptr1->call some method(ptr2);
    > }
    >
    > Code with assertions
    > func1(Ptr1 * ptr1, Ptr2 * ptr2)
    > {
    > assert( ptr1!= NULL && ptr2 != NULL); // And do this for all
    > functions with arguments everywhere
    > ptr2->do something...
    > ptr1->call some method(ptr2);
    > }
    >
    > so my questions really is : Is it a good idea to put the assertions for
    > the function arguments like shown above? Why or why not?


    One way to look at a function call is as a contract between two
    parties: the caller promises that certain things will be true before
    making the function call (these are known as the preconditions), while
    the callee (the function being called) makes certain promises about
    what will be true after the function call completes (these known as the
    postconditions). Assertions are used during development to check that
    both sides are holding up their ends of bargain. And when errors are
    detected, it is clear whether the error is located in the client's code
    or in the function being called.

    In this case, an assert that checks for NULL pointer parameters would
    mean that the client has promised never to pass a NULL pointer as a
    parameter. So a precondition of calling this routine is that all
    pointer parameters be non-NULL. But much of the reason for passing an
    argument by pointer is to allow certain values to be missing (or
    optional). So if the value must be present it makes more sense to
    declare the function with a reference parameter, since doing so better
    communicates to the client the necessary preconditions. And if a
    reference is for some reason impractical, at least the function
    declaration could use a typedef, for instance an IntRef instead of an
    int * to help convey to the caller that although the parameter type is
    in fact a pointer, it is expected to refer to an extant instance of the
    pointer type and not be NULL.

    A great many bugs in software can be traced to vague notions about a
    function's preconditions and postconditions. Clearly defining both, and
    using assertions to verify compliance during development are two of the
    most effective ways to assure quality in the finished application.

    Greg
     
    Greg, Feb 16, 2006
    #11
  12. Divick

    Guest

    Divick wrote:
    > Hi,
    > is it a nice idea to do assetion checks for method arguments ? I
    > am currently redesigning a piece of code. Now the problem is that there
    > are some assumptions for the method arguments that the code makes. It
    > is not checking the validity of the arguments everywhere because that
    > would lead to performance penalty. So I am think that at least
    > assertions will be able check the arguments at least for debug version
    > to verify the design. But now it means that I put the assertions
    > everywhere in the code, something like below:
    >
    > Code with out checks
    >
    > func1(Ptr1 * ptr1, Ptr2 * ptr2)
    > {
    > ptr2->do something...
    > ptr1->call some method(ptr2);
    > }
    >
    > Code with assertions
    > func1(Ptr1 * ptr1, Ptr2 * ptr2)
    > {
    > assert( ptr1!= NULL && ptr2 != NULL); // And do this for all
    > functions with arguments everywhere
    > ptr2->do something...
    > ptr1->call some method(ptr2);
    > }
    >
    > so my questions really is : Is it a good idea to put the assertions for
    > the function arguments like shown above? Why or why not?


    In this particular case, it's not a good idea to check parameters. All
    you need to do is specify in the contract of your interface that the
    behavior is undefined unless the parameters are valid. In most cases,
    you should assume that the behavior is undefined if you pass a null
    pointer where a pointer argument is expected. Thus, you typically
    specify when you *can* pass a null pointer, rather than when you can't.

    The place you do want to use assertions is to verify invariants. For
    example, if you have a class that represents a positive integer, you
    want to assert that the representation is a positive integer. Usually
    you can do this in the destructor. This lets you use the class without
    much performance penalty, but still catch "impossible" errors.
     
    , Feb 16, 2006
    #12
  13. Divick

    Guest

    Greg wrote:

    > But much of the reason for passing an
    > argument by pointer is to allow certain values to be missing (or
    > optional). So if the value must be present it makes more sense to
    > declare the function with a reference parameter, since doing so better
    > communicates to the client the necessary preconditions.


    I have to disagree with this. Using a (modifiable) reference argument
    to enforce the precondition that a valid (i.e., "non-null") argument
    must be supplied obfuscates the possibility that the value will be
    modified. OTOH, any time a non-const pointer is used as an argument,
    the caller must always assume that the value will be modified. This is
    a long-standing opinion.

    > And if a
    > reference is for some reason impractical, at least the function
    > declaration could use a typedef, for instance an IntRef instead of an
    > int * to help convey to the caller that although the parameter type is
    > in fact a pointer, it is expected to refer to an extant instance of the
    > pointer type and not be NULL.


    This kind of typedef is of no use to anyone. In no way does it imply
    that the parameter cannot by NULL. In fact, it doesn't even indicate
    that the parameter is a pointer. It just obfuscates the interface.

    > A great many bugs in software can be traced to vague notions about a
    > function's preconditions and postconditions. Clearly defining both, and
    > using assertions to verify compliance during development are two of the
    > most effective ways to assure quality in the finished application.


    I do agree with this. All you need is a clearly defined contract, and
    possibly some assertions (to verify invariants).
     
    , Feb 16, 2006
    #13
  14. Divick

    Guest

    wrote:
    > Greg wrote:
    >
    > > But much of the reason for passing an
    > > argument by pointer is to allow certain values to be missing (or
    > > optional). So if the value must be present it makes more sense to
    > > declare the function with a reference parameter, since doing so better
    > > communicates to the client the necessary preconditions.

    >
    > I have to disagree with this. Using a (modifiable) reference argument
    > to enforce the precondition that a valid (i.e., "non-null") argument
    > must be supplied obfuscates the possibility that the value will be
    > modified. OTOH, any time a non-const pointer is used as an argument,
    > the caller must always assume that the value will be modified. This is
    > a long-standing opinion.


    There's no reason why a reference has to be modifiable. Pointer or
    reference, both cases you use const to mean, "I'm not going to modify
    this."
     
    , Feb 16, 2006
    #14
  15. Divick

    Greg Guest

    wrote:
    > Greg wrote:
    >
    > > But much of the reason for passing an
    > > argument by pointer is to allow certain values to be missing (or
    > > optional). So if the value must be present it makes more sense to
    > > declare the function with a reference parameter, since doing so better
    > > communicates to the client the necessary preconditions.

    >
    > I have to disagree with this. Using a (modifiable) reference argument
    > to enforce the precondition that a valid (i.e., "non-null") argument
    > must be supplied obfuscates the possibility that the value will be
    > modified. OTOH, any time a non-const pointer is used as an argument,
    > the caller must always assume that the value will be modified. This is
    > a long-standing opinion.


    Why would the client be calling the function unless the client knows
    the reason for calling the routine and what the routine does? If the
    client knows what and why it it is calling a function, than the fact
    that some parameters may be references whose value may change is all
    well and good, since that type of change is precisely why the function
    is being called.

    The idea that it must be clear whether a parameter in a function call
    is a pointer or a reference or a value is a crutch left over from C.
    Such an emphasis simply means that the program isn't really sure what
    it is doing and has to limit the bad consequences that flow from that
    fact.

    > > And if a
    > > reference is for some reason impractical, at least the function
    > > declaration could use a typedef, for instance an IntRef instead of an
    > > int * to help convey to the caller that although the parameter type is
    > > in fact a pointer, it is expected to refer to an extant instance of the
    > > pointer type and not be NULL.

    >
    > This kind of typedef is of no use to anyone. In no way does it imply
    > that the parameter cannot by NULL. In fact, it doesn't even indicate
    > that the parameter is a pointer. It just obfuscates the interface.


    This technique is commonly used in many well known and widely used
    APIs. Such a typedef is usually called a "Handle", that is, a reference
    to some (often opaque) data structure that the client passes to various
    routines in an API. A client needs a valid Handle in order to call
    these routines. It cannot pass NULL even though the Handle's type is in
    fact a pointer.

    It is far more important to focus on the meaning of the parameters to a
    function call rather than their form. Fixating on pointers vs.
    references vs. value is the wrong emphasis since it tries to limit what
    can happen in the function call. Instead the proper focus should be on
    what the client can expect to be true after the function call
    completes.

    Greg
     
    Greg, Feb 17, 2006
    #15
    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. Razvan

    Proper use of assertions

    Razvan, Oct 7, 2004, in forum: Java
    Replies:
    5
    Views:
    492
  2. P. Chalin

    use of assertions in practice

    P. Chalin, Mar 26, 2005, in forum: Java
    Replies:
    0
    Views:
    402
    P. Chalin
    Mar 26, 2005
  3. P. Chalin

    use of assertions in practice

    P. Chalin, Mar 26, 2005, in forum: C++
    Replies:
    0
    Views:
    356
    P. Chalin
    Mar 26, 2005
  4. P. Chalin

    use of assertions in practice

    P. Chalin, Mar 26, 2005, in forum: C Programming
    Replies:
    0
    Views:
    333
    P. Chalin
    Mar 26, 2005
  5. Eileen
    Replies:
    5
    Views:
    387
Loading...

Share This Page