Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > assert in C

Reply
Thread Tools

assert in C

 
 
Keith Thompson
Guest
Posts: n/a
 
      12-26-2009
"(E-Mail Removed)" <(E-Mail Removed)> writes:
> On Dec 26, 4:51*am, Keith Thompson <(E-Mail Removed)> wrote:
>> "(E-Mail Removed)" <(E-Mail Removed)> writes:

[...]
>> > while, how about the -O option in gcc? can this make assert not
>> > workable?

>>
>> No, the "-O" option doesn't affect the behavior of assert. *Why did
>> you think it would?

>
> OK, then if I compile the c program in release mode, the assert
> statement should not workable, is it wrong?
> If it is wrong, then how to disable the assert statement by gcc?


It depends on what you mean by "release mode". That's not a term
defined either by the C language or, as far as I can tell, by gcc.

Defining the macro NDEBUG before the "#include <assert.h>"
disables asserts. You can do that by adding "#define NDEBUG"
to your source code, or by using some compiler-specific option.
For gcc (and some other compilers), the option is "-DNDEBUG".

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
 
 
 
cuiyouzhi0000@gmail.com
Guest
Posts: n/a
 
      12-27-2009
On Dec 27, 12:08*am, Eric Sosman <(E-Mail Removed)> wrote:
> >> It is. asserts suck and are the sign of sloppy programmers who only use
> >> them to appear to be concerned about reliability. An assert condition
> >> should simply not occur.

>
> > I don't agree that assert condition should simply not occur.
> > such as, assert NULL pointer, I think it can occur at high
> > possibility.

>
> * * *The claim that "asserts suck" sucks, but their purpose must
> be properly understood: They are useful to the programmer, but
> not to the end user. *They can alert the programmer to programming
> errors, but are not good for things like validating user input.
>
> * * *Since an unsuccessful assert() terminates the program (unless
> you're doing tricky things with SIGABRT), an assert() that fires
> with "high probability" means the program dies with that same
> high probability -- which indicates that the program is not very
> useful, because it keeps dying!


Then you thought that the assert can be used to debug the program,
not for error handling.

In the debug side, we used assert to check if all tests passed or
not,
if passed, then we can disable the assert statements in nodebug mode
for
it cost any time.

I am clear now, I think. We should design another
way to handle error code, such as by return status. Am I right?
>
> > So, gcc -NDEBUG -g *.c *.c -o * will work without assert?

>
> * * *The command line as shown will probably not work at all.
> Changing it to something like "gcc -DNDEBUG -g *.c" will cause
> the NDEBUG macro to be defined at the start of each .c file's
> compilation. *If it's still defined when <assert.h> is included
> (that is, if you don't #undef it first), the assert() calls in
> that file will expand to no-ops that have no effect on the
> program's execution.


Ah, yes, we should add -D before NDEBUG, thanks.

 
Reply With Quote
 
 
 
 
Nick
Guest
Posts: n/a
 
      12-27-2009
Richard Heathfield <(E-Mail Removed)> writes:

> In
> <(E-Mail Removed)>,
> (E-Mail Removed) wrote:
>
> <snip>
>
>> Then you thought that the assert can be used to debug the program,
>> not for error handling.

>
> Assertions were never intended to handle errors. Their purpose is to
> allow you to make explicit your assumptions about the state of your
> program at a given point so that, if ever a situation arises where
> those assumptions don't hold, you can get the program to tell you
> about it - by aborting with a message giving you the file name and
> line number of the broken assumption.
>
> Nobody would ever want to use such a cumbersome "all or nothing"
> mechanism for error-handling.
>
> p = fgets(buf, sizeof buf, stdin);
> assert(p != NULL); /* daft */
>
> but for assumption-checking, it works well:
>
> new = tree_insert(&tree, data, sizeof data);
> if(new != NULL)
> {
> assert(tree_balances(&tree));
> /* ... if okay, carry on... */
> }
> else
> {
> /* ...handle insertion error ... */


That also provides a bit of documentation - on reading the code it's
obvious that the programmer expects the tree to be balanced after
insertion, so you don't sit there thinking "I wonder if tree_insert
always returns a balanced tree?".
--
Online waterways route planner: http://canalplan.org.uk
development version: http://canalplan.eu
 
Reply With Quote
 
Squeamizh
Guest
Posts: n/a
 
      12-27-2009
On Dec 26, 8:35*am, Richard <(E-Mail Removed)> wrote:
> Eric Sosman <(E-Mail Removed)> writes:
> > On 12/26/2009 10:27 AM, (E-Mail Removed) wrote:
> >> On Dec 26, 10:31 pm, Richard<(E-Mail Removed)> *wrote:
> >>[...]
> >>> It is. asserts suck and are the sign of sloppy programmers who only use
> >>> them to appear to be concerned about reliability. An assert condition
> >>> should simply not occur.

>
> >> I don't agree that assert condition should simply not occur.
> >> such as, assert NULL pointer, I think it can occur at high
> >> possibility.

>
> > * * *The claim that "asserts suck" sucks, but their purpose must
> > be properly understood: They are useful to the programmer, but
> > not to the end user. *They can alert the programmer to programming
> > errors, but are not good for things like validating user input.

>
> > * * *Since an unsuccessful assert() terminates the program (unless
> > you're doing tricky things with SIGABRT), an assert() that fires
> > with "high probability" means the program dies with that same
> > high probability -- which indicates that the program is not very
> > useful, because it keeps dying!

>
> >> So, gcc -NDEBUG -g *.c *.c -o * will work without assert?

>
> > * * *The command line as shown will probably not work at all.
> > Changing it to something like "gcc -DNDEBUG -g *.c" will cause
> > the NDEBUG macro to be defined at the start of each .c file's
> > compilation. *If it's still defined when <assert.h> is included
> > (that is, if you don't #undef it first), the assert() calls in
> > that file will expand to no-ops that have no effect on the
> > program's execution.

>
> Asserts suck because of the termination. In 99% of test cases where that
> assert triggers you can also merely run the program in a debugger and
> get a backtrace there and then and "live debug". Asserts, like
> littering code with printfs, is amateur and sucks in most cases I have
> come across them polluting the code.


That doesn't make sense. A lot of times the assert gets triggered
under a very specific set of conditions that might not even be
something you can test in your lab environment. Running the program
in a debugger does nothing to reproduce that kind of problem.

Consider a watchdog task in an embedded system. If a task is hung due
to a unforeseen set of peculiar circumstances, the periodic assertion
that all tasks have checked in can be invaluable. I can't think of
any obvious alternative to debugging this kind of problem.

Where I work, a failed assertion generates a coredump in our
production code. The ability to see what state the device was in when
something has gone unexpectedly wrong in the field has proven to be
extremely valuable. It isn't about programmer laziness; quite the
opposite. Diligent sanity checking through the use of asserts is a
means of proactively providing visibility into the problems that will
invariably arise one the product is put to actual use.

>
> --
> "Avoid hyperbole at all costs, its the most destructive argument on
> the planet" - Mark McIntyre in comp.lang.c


 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      12-27-2009
On 12/26/2009 11:37 PM, (E-Mail Removed) wrote:
> On Dec 27, 12:08 am, Eric Sosman<(E-Mail Removed)> wrote:
>> [...]
>> Since an unsuccessful assert() terminates the program (unless
>> you're doing tricky things with SIGABRT), an assert() that fires
>> with "high probability" means the program dies with that same
>> high probability -- which indicates that the program is not very
>> useful, because it keeps dying!

>
> Then you thought that the assert can be used to debug the program,
> not for error handling.


Yes, more or less. The actual effect of an assert() is
to cause a programming error to behave predictably and quite
visibly, which is useful as a starting point for debugging.

> In the debug side, we used assert to check if all tests passed or
> not,
> if passed, then we can disable the assert statements in nodebug mode
> for
> it cost any time.


There are two (or more) schools of thought on this topic.
One approach sprinkles assert() liberally throughout the code
during development and then disables them all for "release"
versions or when performance measurements become important.
Another says "ship what you tested" and leaves the assert()
calls enabled even in the final product, the idea being that
the end user may do things the test suite didn't anticipate.

In large projects a blended strategy may be used: Load the
code with tons and tons of assert() calls during development,
tagging each with an "importance" or "level." In the release
version, disable the less important calls but leave the critical
assertions intact. Sometimes a wrapper along the lines of

extern enum { RELEASE, NORMAL, PARANOID } debugLevel;
#define ASSERT(level,truth) \
assert(debugLevel < (level) || (truth))
...
session = idToSession(sessionID);
ASSERT(RELEASE, session != NULL);
...
ASSERT(PARANOID, expensiveSanityCheck());
...

.... can be used for the "tagging."

> I am clear now, I think. We should design another
> way to handle error code, such as by return status. Am I right?


It depends on what you mean by "error." Usually, there
are many possible kinds of error, including (but not limited to)

- Logic errors: The programmer reasoned incorrectly or from
incorrect precepts, so the code does not behave as desired

- Implementation errors: The programmer chose the right
algorithm, but slipped up in coding it

- Environmental errors: The code is fine, but for some reason
the "configfile.dat" file can't be opened

- User errors: While running the program, the user entered
his date of birth as 1964-02-30

An assert() can be helpful in cases like the first two, but is
probably not appropriate for the final two.

>>> So, gcc -NDEBUG -g *.c *.c -o * will work without assert?

>>
>> The command line as shown will probably not work at all.
>> Changing it to something like "gcc -DNDEBUG -g *.c" will cause
>> the NDEBUG macro to be defined at the start of each .c file's
>> compilation. If it's still defined when<assert.h> is included
>> (that is, if you don't #undef it first), the assert() calls in
>> that file will expand to no-ops that have no effect on the
>> program's execution.

>
> Ah, yes, we should add -D before NDEBUG, thanks.


You might also want to review just how many .c files are
being compiled, and where the -o sends the output ...

--
Eric Sosman
(E-Mail Removed)lid
 
Reply With Quote
 
Beej Jorgensen
Guest
Posts: n/a
 
      12-28-2009
On 12/26/2009 07:55 AM, Richard wrote:
> "I dont need to rigorously test my code flow and ensure things are
> only called with valid parameters (eg non null pointers) because if
> they are called with null pointers the assert will trap it". It's
> for the lazy.


Bah, I just tripped one of my asserts just the other day. There were
two entities in the game that would interrogate one another for
information. I added a new state to one of the entities, but forgot to
prep the other one for it.

When it ran, the second entity saw the new state, didn't know what to do
with it, and asserted. And I thought, "Oh yeah--this guy needs to react
to that."

Whether lazy, sloppy, or just too late at night, I'm glad I put that
assert in there.

I agree that programmers should know to not rely on asserts for
production code.

-Beej

 
Reply With Quote
 
cuiyouzhi0000@gmail.com
Guest
Posts: n/a
 
      12-28-2009
On Dec 27, 10:32*pm, Eric Sosman <(E-Mail Removed)> wrote:
>
> * * *There are two (or more) schools of thought on this topic.
> One approach sprinkles assert() liberally throughout the code
> during development and then disables them all for "release"
> versions or when performance measurements become important.
> Another says "ship what you tested" and leaves the assert()
> calls enabled even in the final product, the idea being that
> the end user may do things the test suite didn't anticipate.
>
> * * *In large projects a blended strategy may be used: Load the
> code with tons and tons of assert() calls during development,
> tagging each with an "importance" or "level." *In the release
> version, disable the less important calls but leave the critical
> assertions intact. *Sometimes a wrapper along the lines of
>
> * * * * extern enum { RELEASE, NORMAL, PARANOID } debugLevel;


looks debugLevel here was assigned at other place.

> * * * * #define ASSERT(level,truth) \
> * * * * * * assert(debugLevel < (level) || (truth))


ASSERT can be controlled by debugLevel

> * * * * ...
> * * * * session = idToSession(sessionID);
> * * * * ASSERT(RELEASE, session != NULL);
> * * * * ...
> * * * * ASSERT(PARANOID, expensiveSanityCheck());
> * * * * ...
>
> ... can be used for the "tagging."


Good way to control assert in large project indeed.
While, I donot

>
> > I am clear now, I think. We should design another
> > way to handle error code, such as by return status. Am I right?

>
> * * *It depends on what you mean by "error." *Usually, there
> are many possible kinds of error, including (but not limited to)
>
> * * *- Logic errors: The programmer reasoned incorrectly or from
> * * * *incorrect precepts, so the code does not behave as desired
>
> * * *- Implementation errors: The programmer chose the right
> * * * *algorithm, but slipped up in coding it
>
> * * *- Environmental errors: The code is fine, but for some reason
> * * * *the "configfile.dat" file can't be opened
>
> * * *- User errors: While running the program, the user entered
> * * * *his date of birth as 1964-02-30
>
> An assert() can be helpful in cases like the first two, but is
> probably not appropriate for the final two.
>


Good summary about "error", for the first 2 items, we used assert to
debug our programs,
for the others, we really need the error handling method.

So, I agree with you about assert:

* assert can be used in debug and release mode, you can decide by your
case ( such as, control assert by ASSERT above, or disable assert for
performance reason)
* assert often used to debug the wrong stuff in programs, such as
logic error in program and implement error, while, user error and
other env errors should be handled by error code or exceptions.
* -DNODEBUG is used to disable assert by gcc, or define NODEBUG macro
before #include<assert.h>

Anything else need to add?
 
Reply With Quote
 
Nick
Guest
Posts: n/a
 
      12-28-2009
Richard Heathfield <(E-Mail Removed)> writes:

> Beej Jorgensen wrote:
>
> <snip>
>
>> I agree that programmers should know to not rely on asserts for
>> production code.

>
> Likewise. They are a development-time tool. The ease with which they
> can be disabled is wonderful, as it means that we can have all the
> benefits of assertions during development, without any of the hassles
> - extra code, extra time - in the production version.
>
> You will, however, not be surprised to learn that there is a
> considerable body of opinion to the effect that assertions should be
> left *on* in production code. The analogy that this view's supporters
> like to trot out is "you wouldn't take the lifeboats off a ship before
> sending it out to sea"... which just goes to show that proof by
> analogy is fraud. The counter-"proof" is that assertions are like
> scaffolding -
> it's very useful while the building is undergoing construction or
> repair, but you wouldn't want to leave it up during normal usage.


I think one of the reasons for the heat is that there are two different
reasons to use assert - and the arguments apply differently to each.

One is where you are carrying out a very-near-free check: that a pointer
passed to a function isn't NULL for example. Without the assert the
function is going to blow up when you dereference the NULL pointer, so
adding the assert just documents clearly that the pointer mustn't be
NULL, and guarantees a particular failure mode if it gets that way
through a bug elsewhere in the program. These seem good reasons to
leave this sort of assert turned on.

The second is your tree-balance-checking example, where there is
presumably some reasonable cost to carrying out the check. In that case
turning it off in the production code for efficiency reasons makes
sense. Also, perhaps, you might in many cases get away with the tree
being unbalanced, so blowing up in the face of the user isn't the best
response. These seem good reasons to turn this sort of assert off.

In fact, thinking about and writing this makes me wonder about using
assert for the latter and a simple if/abort() line for the former.
--
Online waterways route planner: http://canalplan.org.uk
development version: http://canalplan.eu
 
Reply With Quote
 
cuiyouzhi0000@gmail.com
Guest
Posts: n/a
 
      12-28-2009
On Dec 28, 4:13*pm, Richard Heathfield <(E-Mail Removed)> wrote:
> (E-Mail Removed) wrote:
>
> <snip>
>
> > So, I agree with you about assert:

>
> > * assert can be used in debug and release mode, you can decide by your
> > case ( such as, control assert by ASSERT above, or disable assert for
> > performance reason)

>
> If you need to leave the assertions in your production code, it is not
> yet ready for release.


If I want to keep the assert statements in production code, what else
do
I need to do?

>
> > * assert often used to debug the wrong stuff in programs, such as
> > logic error in program and implement error, while, user error and
> > other env errors should be handled by error code or exceptions.

>
> One might think of it this way: assertions are intended to reveal bugs
> in the program, not bugs in the data. A wrong program needs the
> programmer's attention, but wrong data is, at least in theory,
> susceptible to correction by the user, so one should make it
> (relatively) easy for the user to correct the data, for example by
> offering another opportunity to provide it. One does not do this by
> bombing out of the program.


classify by program error and data error is better.

>
> > * -DNODEBUG is used to disable assert by gcc, or define NODEBUG macro

>
> In another of those mildly infuriating abbrvs, it's NDEBUG, not NODEBUG.
>
> > before #include<assert.h>

>
> Or, slightly more traditionally and readably:
>
> #include <assert.h>


Thanks for correcting the details.

>
> > Anything else need to add?

>
> Yes: don't believe everything you read.
>

sorry, I don't understand this line.
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      12-28-2009
On 12/28/2009 8:52 AM, Richard Heathfield wrote:
> [...]
> You will get conflicting advice from different sources. Don't assume
> that every source is reliable. Many are not.


Also, when two sources disagree, do not assume that
one (at least) of them is unreliable. Even experts differ.

<off-topic reason=anecdote>

A customer once got upset because he heard differing advice
from a software vendor and from my employer about how to tune
my company's hardware to run the other company's software. I
used to employ automotive analogies in such cases, pointing
out that different sources give different advice about how
often to change the engine oil, what kind of oil to use, and
so on. But since this customer was in the automotive industry
I thought perhaps I should avoid that analogy, and went looking
for another.

To prepare for the conference call where this "scandal"
would be aired, I pulled out three cookbooks and looked up their
recipes for guacamole. On the call, I listed the credentials of
the cooks and chefs responsible for the recipes, to establish
their expertise in matters culinary, and then pointed out that
the three books called for different amounts of lemon juice (on
a per-avocado basis). Indeed, one of them used no lemon juice
at all, but recommended lime juice instead!

The point was made: Experts can disagree. And to this day
that customer knows me as The Guacamole Man.

</off-topic>

--
Eric Sosman
(E-Mail Removed)lid
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
To assert or not to assert... ImpalerCore C Programming 79 05-17-2010 12:47 PM
Debug.Assert(): missing MsgBox (VS.NET 2003, C#) Mark Newby ASP .Net 1 05-03-2005 07:43 AM
assert 0, "foo" vs. assert(0, "foo") Thomas Guettler Python 3 02-23-2005 07:53 PM
assert(x) and '#define ASSERT(x) assert(x)' Alex Vinokur C Programming 5 11-25-2004 08:48 PM
RE: remove assert statement (Was: Re: PEP new assert idiom) Robert Brewer Python 1 11-07-2004 06:53 PM



Advertisments