How does assert benefit your code really?

Discussion in 'C Programming' started by lovecreatesbeauty, Apr 11, 2006.

  1. Besides printing out for example

    " a.out: p113.c:8: main: Assertion `0' failed.
    Aborted "

    and a switch option NDEBUG, what other benefits does assert() provide
    in any scope of designing, debugging/coding and/or testing?

    Do you prefer the if statement of the language to the assert MACRO of
    the precompiler?

    --
    lovecreatesbeauty
     
    lovecreatesbeauty, Apr 11, 2006
    #1
    1. Advertising

  2. lovecreatesbeauty

    Kiru Sengal Guest

    lovecreatesbeauty wrote:
    > Besides printing out for example
    >
    > " a.out: p113.c:8: main: Assertion `0' failed.
    > Aborted "
    >
    > and a switch option NDEBUG, what other benefits does assert() provide
    > in any scope of designing, debugging/coding and/or testing?
    >
    > Do you prefer the if statement of the language to the assert MACRO of
    > the precompiler?
    >


    assert is usually used to catch logical errors in your program, that if
    deemed nonexistant after proper testing (noticing that the assert never
    fires), would not require the error checking anymore in your finished
    product
     
    Kiru Sengal, Apr 11, 2006
    #2
    1. Advertising

  3. lovecreatesbeauty

    Pedro Graca Guest

    lovecreatesbeauty wrote:
    > Besides printing out for example
    >
    > " a.out: p113.c:8: main: Assertion `0' failed.
    > Aborted "
    >
    > and a switch option NDEBUG, what other benefits does assert() provide
    > in any scope of designing, debugging/coding and/or testing?
    >
    > Do you prefer the if statement of the language to the assert MACRO of
    > the precompiler?


    [newbie answering]
    To me, assert() and if() are two completely different things, each used
    for completely different reasons.

    #include <assert.h>
    int main(void) {
    assert(argc >= 2); /* wrong use of assert() */
    if (CHAR_BIT > 8) { /* wrong use of if() */
    exit(EXIT_FAILURE);
    }
    return 0;
    }


    Or, for a more likely example, let's say you have a function that sums
    all the int's in an array of some size. In the function description you
    say the array must not be empty.

    int sum_array(const int * array, size_t elems) {
    int x = 0;
    assert(array != NULL);
    while (elems--) x += *array++;
    return x;
    }

    When this code is compiled with NDEBUG defined there will be no checks
    in place to catch programmer's mistakes.

    --
    If you're posting through Google read <http://cfaj.freeshell.org/google>
     
    Pedro Graca, Apr 11, 2006
    #3
  4. lovecreatesbeauty

    Bill Pursell Guest

    lovecreatesbeauty wrote:
    > Besides printing out for example
    >
    > " a.out: p113.c:8: main: Assertion `0' failed.
    > Aborted "
    >
    > and a switch option NDEBUG, what other benefits does assert() provide
    > in any scope of designing, debugging/coding and/or testing?
    >
    > Do you prefer the if statement of the language to the assert MACRO of
    > the precompiler?


    Assert can be your best friend. For example, if instead of:
    int
    foo(int x, int y)
    { /* Return some function of x and y. Remember, x needs
    to be between 5 and 10, and y must be between 15 and 150
    or this will segfault!! */
    ....
    }

    you write:
    int
    foo(int x, int y)
    {
    assert(x > 5 && x <=10);
    assert (y >=15 && y<150);
    ....
    }

    You get 2 major benefits.
    1) Removes the ambiguity inherent in the English description
    regarding whether the endpoints are inclusive,
    2) When some code is changed so that a caller is using
    the wrong arguments, you will be instantly aware of it
    when you run, instead of getting a random segfault and
    having to track down what caused it.

    Also, placing assertions makes it clear to the maintainer
    what the coder expected. Any time you expect something
    to be true, place an assertion. If it fails, you either have
    a coding error somewhere, or your expectation is wrong.
    Either is good to know.

    Assert is better than if for this type of thing, because it goes
    away when you compile your non-debug version. You can
    accomplish that with precompiler wrappers around your
    if statements, but it is aesthetically unappealing in most
    cases.
     
    Bill Pursell, Apr 11, 2006
    #4
  5. "lovecreatesbeauty" <> writes:

    > Besides printing out for example
    >
    > " a.out: p113.c:8: main: Assertion `0' failed.
    > Aborted "
    >
    > and a switch option NDEBUG, what other benefits does assert() provide
    > in any scope of designing, debugging/coding and/or testing?
    >
    > Do you prefer the if statement of the language to the assert MACRO of
    > the precompiler?



    One thing you must be really careful of is that the assert() call must
    not have any side effects. Otherwise, even after all your extensive
    testing is done, the final build will be different and may fail. And
    because it only fails when the asserts are gone, you won't know where
    the problem is!

    for example,

    ....
    unsigned char *fred;
    assert((fred = malloc(1000)) != 0);
    memset(fred,0,1000);
    ....

    would be a disaster since no memory would get allocated in the release
    build.

    A stupid mistake... but I did it once!

    Also in embedded systems or time or memory critical code, the overhead
    of the asserts may be too high to even run the program properly. For
    example assert() may bring in printf and the rest of the stdio
    library.


    --

    John Devereux
     
    John Devereux, Apr 11, 2006
    #5
  6. lovecreatesbeauty

    pemo Guest

    John Devereux wrote:
    > "lovecreatesbeauty" <> writes:
    >
    >> Besides printing out for example
    >>
    >> " a.out: p113.c:8: main: Assertion `0' failed.
    >> Aborted "
    >>
    >> and a switch option NDEBUG, what other benefits does assert() provide
    >> in any scope of designing, debugging/coding and/or testing?
    >>
    >> Do you prefer the if statement of the language to the assert MACRO of
    >> the precompiler?

    >
    >
    > One thing you must be really careful of is that the assert() call must
    > not have any side effects. Otherwise, even after all your extensive
    > testing is done, the final build will be different and may fail. And
    > because it only fails when the asserts are gone, you won't know where
    > the problem is!
    >
    > for example,
    >
    > ....
    > unsigned char *fred;
    > assert((fred = malloc(1000)) != 0);
    > memset(fred,0,1000);
    > ....
    >
    > would be a disaster since no memory would get allocated in the release
    > build.
    >
    > A stupid mistake... but I did it once!
    >
    > Also in embedded systems or time or memory critical code, the overhead
    > of the asserts may be too high to even run the program properly. For
    > example assert() may bring in printf and the rest of the stdio
    > library.


    A very good point about the 'type' of things that should/should-not be
    /asserted/.

    For example, should this be /asserted/ ...

    char * p = malloc(10);

    assert(p != NULL);

    malloc() can legitimably return NULL, so, is this worth asserting, or should
    one really build in a proper test, and, if the test proves negative, the
    more difficult 'recovery'?

    char * p = malloc(10);

    if(NULL == p)
    {
    // Now what? It's all too easy to call abort() etc?
    }


    --
    ==============
    *Not a pedant*
    ==============
     
    pemo, Apr 11, 2006
    #6
  7. lovecreatesbeauty

    Ian Collins Guest

    John Devereux wrote:
    >
    > Also in embedded systems or time or memory critical code, the overhead
    > of the asserts may be too high to even run the program properly. For
    > example assert() may bring in printf and the rest of the stdio
    > library.
    >

    That's where it pays to roll one's own assert macro. If the device has
    no means to display the message, don't.

    --
    Ian Collins.
     
    Ian Collins, Apr 11, 2006
    #7
  8. On 2006-04-11, Kiru Sengal <> wrote:
    >
    > lovecreatesbeauty wrote:
    > assert is usually used to catch logical errors in your program, that if
    > deemed nonexistant after proper testing (noticing that the assert never
    > fires), would not require the error checking anymore in your finished
    > product
    >


    Sometimes, leaving in a few of those assert statements in the finished
    product is a good idea as well because it will give a better indication
    of where things fail in production builds (because of misuse of the
    program, not buggy coding). I've seen this method being useful in the
    printer driver I maintain (a driver to use a certain GDI printer under
    *nix-like OS), so I thought sharing this "trick" with others (who might
    not yet know it) might be a good idea.

    Regards

    Manuel
     
    Manuel Tobias Schiller, Apr 11, 2006
    #8
  9. Ian Collins <> writes:

    > John Devereux wrote:
    >>
    >> Also in embedded systems or time or memory critical code, the overhead
    >> of the asserts may be too high to even run the program properly. For
    >> example assert() may bring in printf and the rest of the stdio
    >> library.
    >>

    > That's where it pays to roll one's own assert macro. If the device has
    > no means to display the message, don't.


    That's what I usually do. For some platforms I set it to just halt the
    program, then at least you can usually see what happened in a
    debugger.

    --

    John Devereux
     
    John Devereux, Apr 11, 2006
    #9
  10. "Manuel Tobias Schiller" <> wrote in message
    news:...
    > Sometimes, leaving in a few of those assert statements in the finished
    > product is a good idea as well because it will give a better indication
    > of where things fail in production builds (because of misuse of the
    > program, not buggy coding). I've seen this method being useful in the
    > printer driver I maintain (a driver to use a certain GDI printer under
    > *nix-like OS), so I thought sharing this "trick" with others (who might
    > not yet know it) might be a good idea.


    Robust code should have all kinds of error-checking built in so that if the
    impossible happens, it can be silently dealt with. Aborting a production
    build in customers' hands is rarely the correct answer.

    assert() is useful because, whenever you code in those checks to handle the
    impossible, you can put an assert() right before them and crash the code in
    a development build (where such is somewhat expected). This prevents bad
    things from silently "working" as they would in the production build.

    For instance, most of the time when I write a function that is documented to
    accept only a non-NULL pointer as a parameter, it'll look like this:

    void func(void *param) {

    assert(param);
    if (!param) return;

    /* do useful stuff with param */

    }

    Anyone using my function incorrectly in a debug build will get a nasty error
    and crash making it obvious what they did, whereas if it's due to a bug that
    never appeared in testing, the production behavior at least has a chance of
    being correct.

    One might also redefine assert() to print a message to stderr in production
    builds instead of having the test preprocessed out. That's the best of both
    worlds.

    S

    --
    Stephen Sprunk "Stupid people surround themselves with smart
    CCIE #3723 people. Smart people surround themselves with
    K5SSS smart people who disagree with them." --Aaron Sorkin

    *** Free account sponsored by SecureIX.com ***
    *** Encrypt your Internet usage with a free VPN account from http://www.SecureIX.com ***
     
    Stephen Sprunk, Apr 11, 2006
    #10
  11. lovecreatesbeauty

    Ian Collins Guest

    Stephen Sprunk wrote:
    > "Manuel Tobias Schiller" <> wrote in message
    > news:...
    >
    >> Sometimes, leaving in a few of those assert statements in the finished
    >> product is a good idea as well because it will give a better indication
    >> of where things fail in production builds (because of misuse of the
    >> program, not buggy coding). I've seen this method being useful in the
    >> printer driver I maintain (a driver to use a certain GDI printer under
    >> *nix-like OS), so I thought sharing this "trick" with others (who might
    >> not yet know it) might be a good idea.

    >
    >
    > Robust code should have all kinds of error-checking built in so that if
    > the impossible happens, it can be silently dealt with. Aborting a
    > production build in customers' hands is rarely the correct answer.
    >

    Unfortunately, in embedded systems it is often the only option. A
    (quick) reset of the device is often preferable to a lock-up or other
    undefined behaviour.

    --
    Ian Collins.
     
    Ian Collins, Apr 11, 2006
    #11
  12. lovecreatesbeauty

    Ian Collins Guest

    John Devereux wrote:
    > Ian Collins <> writes:
    >
    >
    >>John Devereux wrote:
    >>
    >>>Also in embedded systems or time or memory critical code, the overhead
    >>>of the asserts may be too high to even run the program properly. For
    >>>example assert() may bring in printf and the rest of the stdio
    >>>library.
    >>>

    >>
    >>That's where it pays to roll one's own assert macro. If the device has
    >>no means to display the message, don't.

    >
    >
    > That's what I usually do. For some platforms I set it to just halt the
    > program, then at least you can usually see what happened in a
    > debugger.
    >

    On embedded devices, I prefer to log an error message (if possible) and
    reset. At least with a log, service personnel can see what has happened
    to the device if it is returned as faulty.

    --
    Ian Collins.
     
    Ian Collins, Apr 12, 2006
    #12
  13. lovecreatesbeauty

    CBFalconer Guest

    Manuel Tobias Schiller wrote:
    > On 2006-04-11, Kiru Sengal <> wrote:
    >>
    >> assert is usually used to catch logical errors in your program,
    >> that if deemed nonexistant after proper testing (noticing that
    >> the assert never fires), would not require the error checking
    >> anymore in your finished product

    >
    > Sometimes, leaving in a few of those assert statements in the
    > finished product is a good idea as well because it will give a
    > better indication of where things fail in production builds
    > (because of misuse of the program, not buggy coding). I've seen
    > this method being useful in the printer driver I maintain (a
    > driver to use a certain GDI printer under *nix-like OS), so I
    > thought sharing this "trick" with others (who might not yet
    > know it) might be a good idea.


    Nonsense, to put it mildly. The only asserts that should be left
    in production code should be intended to catch hardware errors. It
    should not be possible to trigger them in any other manner.

    --
    "If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson
    More details at: <http://cfaj.freeshell.org/google/>
    Also see <http://www.safalra.com/special/googlegroupsreply/>
     
    CBFalconer, Apr 12, 2006
    #13
  14. Ian Collins <> writes:

    > John Devereux wrote:
    >> Ian Collins <> writes:
    >>
    >>
    >>>John Devereux wrote:
    >>>
    >>>>Also in embedded systems or time or memory critical code, the overhead
    >>>>of the asserts may be too high to even run the program properly. For
    >>>>example assert() may bring in printf and the rest of the stdio
    >>>>library.
    >>>>
    >>>
    >>>That's where it pays to roll one's own assert macro. If the device has
    >>>no means to display the message, don't.

    >>
    >>
    >> That's what I usually do. For some platforms I set it to just halt the
    >> program, then at least you can usually see what happened in a
    >> debugger.
    >>

    > On embedded devices, I prefer to log an error message (if possible) and
    > reset. At least with a log, service personnel can see what has happened
    > to the device if it is returned as faulty.


    Ah, so you leave the asserts in the production code? Not saying that
    is always bad, but I think it is not the normal (assumed) usage. AFAIK
    the main thing that distinguishes the standard assert() is that it is
    removed when NDEBUG is defined.

    --

    John Devereux
     
    John Devereux, Apr 12, 2006
    #14
  15. "Stephen Sprunk" <> writes:
    [...]
    > For instance, most of the time when I write a function that is
    > documented to accept only a non-NULL pointer as a parameter, it'll
    > look like this:
    >
    > void func(void *param) {
    >
    > assert(param);
    > if (!param) return;
    >
    > /* do useful stuff with param */
    >
    > }


    In C90, assert()'s argument is required to be of type int, so this
    isn't guaranteed to work (though any reasonable definition of assert()
    is unlikely to care). In C99, the argument merely has to be a scalar,
    so the call is legal. Nevertheless, I prefer the more explicit:

    assert(param != NULL);

    both because I find it clearer in the source code, and because the
    argument is stringized and used in the error message:

    assertion "param != NULL" failed: file "tmp.c", line 6

    [...]
    > One might also redefine assert() to print a message to stderr in
    > production builds instead of having the test preprocessed out. That's
    > the best of both worlds.


    I'm not sure you can legally do that. What you can do is define an
    assert-like macro with a different name.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Apr 12, 2006
    #15
  16. lovecreatesbeauty

    Ian Collins Guest

    John Devereux wrote:
    > Ian Collins <> writes:
    >
    >
    >>John Devereux wrote:
    >>
    >>>Ian Collins <> writes:
    >>>
    >>>
    >>>
    >>>>John Devereux wrote:
    >>>>
    >>>>
    >>>>>Also in embedded systems or time or memory critical code, the overhead
    >>>>>of the asserts may be too high to even run the program properly. For
    >>>>>example assert() may bring in printf and the rest of the stdio
    >>>>>library.
    >>>>>
    >>>>
    >>>>That's where it pays to roll one's own assert macro. If the device has
    >>>>no means to display the message, don't.
    >>>
    >>>
    >>>That's what I usually do. For some platforms I set it to just halt the
    >>>program, then at least you can usually see what happened in a
    >>>debugger.
    >>>

    >>
    >>On embedded devices, I prefer to log an error message (if possible) and
    >>reset. At least with a log, service personnel can see what has happened
    >>to the device if it is returned as faulty.

    >
    >
    > Ah, so you leave the asserts in the production code? Not saying that
    > is always bad, but I think it is not the normal (assumed) usage. AFAIK
    > the main thing that distinguishes the standard assert() is that it is
    > removed when NDEBUG is defined.
    >

    Always expect the unexpected!

    --
    Ian Collins.
     
    Ian Collins, Apr 12, 2006
    #16
  17. lovecreatesbeauty

    Ian Collins Guest

    CBFalconer wrote:
    > Manuel Tobias Schiller wrote:
    >
    >>On 2006-04-11, Kiru Sengal <> wrote:
    >>
    >>>assert is usually used to catch logical errors in your program,
    >>>that if deemed nonexistant after proper testing (noticing that
    >>>the assert never fires), would not require the error checking
    >>>anymore in your finished product

    >>
    >>Sometimes, leaving in a few of those assert statements in the
    >>finished product is a good idea as well because it will give a
    >>better indication of where things fail in production builds
    >>(because of misuse of the program, not buggy coding). I've seen
    >>this method being useful in the printer driver I maintain (a
    >>driver to use a certain GDI printer under *nix-like OS), so I
    >>thought sharing this "trick" with others (who might not yet
    >>know it) might be a good idea.

    >
    >
    > Nonsense, to put it mildly. The only asserts that should be left
    > in production code should be intended to catch hardware errors. It
    > should not be possible to trigger them in any other manner.
    >

    I disagree, they can be useful to catch error conditions that slipped
    through testing.

    --
    Ian Collins.
     
    Ian Collins, Apr 12, 2006
    #17
  18. Ian Collins <> writes:
    > CBFalconer wrote:
    >> Manuel Tobias Schiller wrote:
    >>
    >>>On 2006-04-11, Kiru Sengal <> wrote:
    >>>
    >>>>assert is usually used to catch logical errors in your program,
    >>>>that if deemed nonexistant after proper testing (noticing that
    >>>>the assert never fires), would not require the error checking
    >>>>anymore in your finished product
    >>>
    >>>Sometimes, leaving in a few of those assert statements in the
    >>>finished product is a good idea as well because it will give a
    >>>better indication of where things fail in production builds
    >>>(because of misuse of the program, not buggy coding). I've seen
    >>>this method being useful in the printer driver I maintain (a
    >>>driver to use a certain GDI printer under *nix-like OS), so I
    >>>thought sharing this "trick" with others (who might not yet
    >>>know it) might be a good idea.

    >>
    >>
    >> Nonsense, to put it mildly. The only asserts that should be left
    >> in production code should be intended to catch hardware errors. It
    >> should not be possible to trigger them in any other manner.
    >>

    > I disagree, they can be useful to catch error conditions that slipped
    > through testing.


    Agreed. Asserts should not be used in production to handle errors
    that can actually happen (failing to open a vital file, running out of
    memory), but it's reasonable IMHO to use them for
    this-should-never-happen errors (that can show up only if there's a
    bug in the program).

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Apr 12, 2006
    #18
  19. lovecreatesbeauty

    pinkfog Guest

    lovecreatesbeauty wrote:
    > Besides printing out for example
    >
    > " a.out: p113.c:8: main: Assertion `0' failed.
    > Aborted "
    >
    > and a switch option NDEBUG, what other benefits does assert() provide
    > in any scope of designing, debugging/coding and/or testing?
    >
    > Do you prefer the if statement of the language to the assert MACRO of
    > the precompiler?
    >
    > --
    > lovecreatesbeauty

    assert just let you avoid the errors which are not expected to happen.
    you use if statement or try_catch statement to mend the errors which
    may happen by accident.
    Hope what i say is right.
     
    pinkfog, Apr 12, 2006
    #19
  20. lovecreatesbeauty

    Michael Mair Guest

    Keith Thompson schrieb:
    > Ian Collins <> writes:
    >>CBFalconer wrote:
    >>>Manuel Tobias Schiller wrote:
    >>>>On 2006-04-11, Kiru Sengal <> wrote:
    >>>>
    >>>>>assert is usually used to catch logical errors in your program,
    >>>>>that if deemed nonexistant after proper testing (noticing that
    >>>>>the assert never fires), would not require the error checking
    >>>>>anymore in your finished product
    >>>>
    >>>>Sometimes, leaving in a few of those assert statements in the
    >>>>finished product is a good idea as well because it will give a
    >>>>better indication of where things fail in production builds
    >>>>(because of misuse of the program, not buggy coding). I've seen
    >>>>this method being useful in the printer driver I maintain (a
    >>>>driver to use a certain GDI printer under *nix-like OS), so I
    >>>>thought sharing this "trick" with others (who might not yet
    >>>>know it) might be a good idea.
    >>>
    >>>Nonsense, to put it mildly. The only asserts that should be left
    >>>in production code should be intended to catch hardware errors. It
    >>>should not be possible to trigger them in any other manner.

    >>
    >>I disagree, they can be useful to catch error conditions that slipped
    >>through testing.

    >
    > Agreed. Asserts should not be used in production to handle errors
    > that can actually happen (failing to open a vital file, running out of
    > memory), but it's reasonable IMHO to use them for
    > this-should-never-happen errors (that can show up only if there's a
    > bug in the program).


    Depends; at my day job, we have "internal" and "release" "asserts".
    The former are used as debugging aid in the debug version, i.e.
    ....
    else
    {
    INTERNAL_ASSERT(0);
    return F;
    }
    where F is a return value indicating failure for a function which
    must not return F in normal circumstances. Even some of the paranoia
    checks work this way. There are some places in the code where
    assumptions that are integral and should always be completely true
    but for hardware errors or some sneaky scenario that one can ask
    for the permission to use a release assert instead. These are rare.
    Usually we have an orderly "death" with numbered error messages even
    for some more obscure cases.


    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
     
    Michael Mair, Apr 12, 2006
    #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. Robert Brewer
    Replies:
    1
    Views:
    505
    bsmith
    Nov 7, 2004
  2. Thomas Guettler

    assert 0, "foo" vs. assert(0, "foo")

    Thomas Guettler, Feb 23, 2005, in forum: Python
    Replies:
    3
    Views:
    2,540
    Carl Banks
    Feb 23, 2005
  3. Replies:
    2
    Views:
    345
  4. Alex Vinokur

    assert(x) and '#define ASSERT(x) assert(x)'

    Alex Vinokur, Nov 25, 2004, in forum: C Programming
    Replies:
    5
    Views:
    937
    Keith Thompson
    Nov 25, 2004
  5. ImpalerCore

    To assert or not to assert...

    ImpalerCore, Apr 27, 2010, in forum: C Programming
    Replies:
    79
    Views:
    1,716
    Richard Bos
    May 17, 2010
Loading...

Share This Page