By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,975 Members | 1,528 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,975 IT Pros & Developers. It's quick & easy.

Use of assert.h

P: n/a
In general, is it considered bad practice to use asserts in production
code?

What about writing a macro that does the same as assert but continues
to work regardless of the state of NDEBUG?

I can see that it would be poor style to use it for commonly
encountered errors, but what about truly exceptional errors that would
rarely if ever be encountered?
Nov 14 '05 #1
Share this Question
Share on Google+
47 Replies


P: n/a
Rob Thorpe wrote:
In general, is it considered bad practice to use asserts in production
code?

What about writing a macro that does the same as assert but continues
to work regardless of the state of NDEBUG?

I can see that it would be poor style to use it for commonly
encountered errors, but what about truly exceptional errors that would
rarely if ever be encountered?


The answer is, it depends.

You have to consider for your specific application what is best.
Possibilities include:

1) Abort the program with an appropriate message.
This can prevent incorrect results from being given and so in a
situation where no answer is better than an incorrect answer (or
corrupting a database for example) this might be the best thing.

2) Return an error status to the calling function.
If the calling function does not handle the error this could lead to
incorrect results or a crash.

3) Reboot the system (most likely to be an option on an embedded
system).

4) Attempt to recover the situation and fall back on 1, 2 or 3 if the
correction appears not to work.

For some items such as a video recorder, option 4 falling back to 3
might be the best solution. For one application I am working on option 1
is best for a lot of errors (prevents the data being corrupted and all
the work required to fix the data) but option 4 falling back to 1 is the
best solution for other types of problem.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Nov 14 '05 #2

P: n/a
On 23 Mar 2005 03:15:46 -0800, Rob Thorpe
<ro***********@antenova.com> wrote:
In general, is it considered bad practice to use asserts in production
code?
I don't think there is any 'general' opinion, it's largely whatever your
employers or customers think. If you mean "leave them in the code with
NDEBUG defined so that they do nothing" I don't see any problem leaving
them there.
What about writing a macro that does the same as assert but continues
to work regardless of the state of NDEBUG?
If it's in interactive code (by which I mean that the user starts the
application and can see error messages) then I don't think that the
default C assert mechanism is normally appropriate. If I'm using a word
processor, for example, I don't want it to exit with a bit of source
code on a command line and/or a core dump, it would be a lot better to
catch the error and display a meaningful message to the user (and
hopefully correct the error at least enough to do an orderly closedown
of any open files).

In non-interactive code (like embedded systems) the correct response may
well be to reboot or halt the system, possibly after writing the error
message into an area from which it can be recovered later. That may
well be all you can do.
I can see that it would be poor style to use it for commonly
encountered errors, but what about truly exceptional errors that would
rarely if ever be encountered?


It depends on the severity of the error. In some applications I've
worked on there have been a set of 'assert' type macros with differing
degrees of severity and actions depending on whether it was compiled as
debug or production. For instance:

Output a message to the user and continue
Output a message to a local file and continue
Output to the system log and continue
Output to the console and continue
Any of those and abort with a core dump
Any of those and abort with no core dump
Abort without trying to output anything because that will fail
Reboot the system

If you're working in a team those things should already be laid down as
standard procedure, if you're starting out then the project designer
should make those sorts of decisions.

Chris C
Nov 14 '05 #3

P: n/a
Rob Thorpe wrote:
In general,
is it considered bad practice to use asserts in production code?

What about writing a macro that does the same as assert
but continues to work regardless of the state of NDEBUG?

I can see that
it would be poor style to use it for commonly encountered errors,
but what about truly exceptional errors
that would rarely if ever be encountered?


You are confused.

The assert macro is designed to trap programming errors (bugs).
After you have finished developing, testing and debugging
your application program, you simply define NDEBUG
and recompile your application before releasing the "production code".
Don't edit your code to remove invocations of assert
because that just provides an opportunity to introduce new bugs.

Diagnostics from assert macros are of no use to users
who may not be programmers themselves.
If you release code without deactivating assert macros,
it means that you are still debugging the code
and that you expect users to assist you in testing your code.
You probably shouldn't call such code "production code".

Never use the assert macro to trap exceptions (what you call errors).
Exceptions are expected but unpredictable events
which cannot be prevented but must be handled when they occur.
By contrast, bugs are unexpected but predictable errors
(once they have been discovered)
that cannot be "handled" except by fixing the bug
and then they are prevented from ever occurring again.

There are no "macros" to trap exceptions.
You must write ad hoc code to detect and handle exceptions.
Nov 14 '05 #4

P: n/a
Rob Thorpe wrote on 23/03/05 :
In general, is it considered bad practice to use asserts in production
code?

What about writing a macro that does the same as assert but continues
to work regardless of the state of NDEBUG?

I can see that it would be poor style to use it for commonly
encountered errors, but what about truly exceptional errors that would
rarely if ever be encountered?


You want CUnit.

http://cunit.sourceforge.net/

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

..sig under repair

Nov 14 '05 #5

P: n/a
In article <1a**************************@posting.google.com >,
ro***********@antenova.com (Rob Thorpe) wrote:
In general, is it considered bad practice to use asserts in production
code?
It depends. You have to assume that your code might do things that you
didn't intend it to do, and you use "assert"s to find these situations.
Such a situation might arise in your production code as well. So you
have to analyse what your code should do in such a situation, and that
depends very much on what the code does and how people are using it.
What about writing a macro that does the same as assert but continues
to work regardless of the state of NDEBUG?
Just put yourself into the role of a user of the software. What will
happen if an assert finds an error? What will be the consequence for the
user? What will happen if an error occurs and the assert doesn't find
it? What will be the consequence for the user then? What consequence
would the user prefer?
I can see that it would be poor style to use it for commonly
encountered errors, but what about truly exceptional errors that would
rarely if ever be encountered?


I would very much hope that your production code doesn't contain any
"commonly encountered errors".
Nov 14 '05 #6

P: n/a

In article <mn***********************@YOURBRAnoos.fr>, "Emmanuel Delahaye" <em***@YOURBRAnoos.fr> writes:
Rob Thorpe wrote on 23/03/05 :
In general, is it considered bad practice to use asserts in production
code?


You want CUnit.

http://cunit.sourceforge.net/


I'm curious why you think a unit-testing tool is relevant to the
question of whether to use asserts in production code.

--
Michael Wojcik mi************@microfocus.com
Nov 14 '05 #7

P: n/a

In article <ch*********************************@slb-newsm1.svr.pol.co.uk>, Christian Bau <ch***********@cbau.freeserve.co.uk> writes:

I would very much hope that your production code doesn't contain any
"commonly encountered errors".


Code does not have to "contain ... commonly encountered errors" in
order to encounter them. It must account for erroneous input,
failures in the implementation (such as memory allocation failure),
and so forth. Those things could be, and are, sometimes trapped with
asserts in development code; Rob, I believe, is correctly noting that
they should not be handled by assert in production code.

My production code is full of error checking, and some of those
branches are not uncommonly taken (for sufficiently generous values
of "common").

Personally, I dislike assert and refrain from using it entirely; in
the time it takes me to insert an assertion, I can write a real, if
minimal, error handler which will do the right thing in both
development and production code.

--
Michael Wojcik mi************@microfocus.com

An intense imaginative activity accompanied by a psychological and moral
passivity is bound eventually to result in a curbing of the growth to
maturity and in consequent artistic repetitiveness and stultification.
-- D. S. Savage
Nov 14 '05 #8

P: n/a
Michael Wojcik wrote:
Christian Bau writes:
I would very much hope that your production code doesn't contain any
"commonly encountered errors".

Code does not have to "contain ... commonly encountered errors" in
order to encounter them. It must account for erroneous input,
failures in the implementation (such as memory allocation failure),
and so forth. Those things could be, and are, sometimes trapped with
asserts in development code; Rob, I believe, is correctly noting that
they should not be handled by assert in production code.

My production code is full of error checking, and some of those
branches are not uncommonly taken (for sufficiently generous values
of "common").

Personally, I dislike assert and refrain from using it entirely; in
the time it takes me to insert an assertion, I can write a real, if
minimal, error handler which will do the right thing in both
development and production code.


You still appear to be confused about the use of the assert macro.
The assert macro is designed only to trap programming errors (bugs).
You can't "handle" programming errors.
All you can do is fix the bug after assert has detected it
then you don't need any code to trap or "handle" it.
That's why you use the NDEBUG macro definition
to turn off the assert macros after you have finished debugging
and you are ready to release "production" code.

What you call "errors" are more accurately described as *exceptions* --
expected but unpredictable events which cannot be prevented
but must be *handled* when they occur.

Nov 14 '05 #9

P: n/a
Michael Wojcik wrote on 24/03/05 :
In article <mn***********************@YOURBRAnoos.fr>, "Emmanuel Delahaye"
<em***@YOURBRAnoos.fr> writes:
Rob Thorpe wrote on 23/03/05 :
In general, is it considered bad practice to use asserts in production
code?


You want CUnit.

http://cunit.sourceforge.net/


I'm curious why you think a unit-testing tool is relevant to the
question of whether to use asserts in production code.


Do you know this tool? Have you used the CU_ASSERT_xxx() macros
provided by the CUnit framework and library ?

It gives another approach (mainly more detailed and subtle) of the use
of assertions macros.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

..sig under repair

Nov 14 '05 #10

P: n/a
Michael Wojcik wrote:
Christian Bau <ch***********@cbau.freeserve.co.uk> writes:

I would very much hope that your production code doesn't contain
any "commonly encountered errors".


Code does not have to "contain ... commonly encountered errors" in
order to encounter them. It must account for erroneous input,
failures in the implementation (such as memory allocation failure),
and so forth. Those things could be, and are, sometimes trapped with
asserts in development code; Rob, I believe, is correctly noting that
they should not be handled by assert in production code.

My production code is full of error checking, and some of those
branches are not uncommonly taken (for sufficiently generous values
of "common").

Personally, I dislike assert and refrain from using it entirely; in
the time it takes me to insert an assertion, I can write a real, if
minimal, error handler which will do the right thing in both
development and production code.


But "quis custodes custodiens" <spelling?> applies. You vet your
data, and believe you have caught everything, thus routine foo will
never receive faulty parameters, and checking and correcting them
is not worth while. The assert in foo catches your faulty
thinking, and does no harm if you are correct. If triggered it
should tell the user "We goofed. Call Michael at 800-555-1212 and
tell him that <whatever> happened in foo", not "error 22".

--
"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
Nov 14 '05 #11

P: n/a
CBFalconer <cb********@yahoo.com> wrote:
Michael Wojcik wrote:
Personally, I dislike assert and refrain from using it entirely; in
the time it takes me to insert an assertion, I can write a real, if
minimal, error handler which will do the right thing in both
development and production code.


But "quis custodes custodiens" <spelling?> applies. You vet your
data, and believe you have caught everything, thus routine foo will
never receive faulty parameters, and checking and correcting them
is not worth while. The assert in foo catches your faulty
thinking, and does no harm if you are correct. If triggered it
should tell the user "We goofed. Call Michael at 800-555-1212 and
tell him that <whatever> happened in foo", not "error 22".


No, if triggered assert() should print a message, usually cryptic and in
any case rarely adaptable, to stderr, where it is hardly ever even seen
by the user, and then crash the program. I'm with Michael here: check
your input before you use it, and if you need an error handler, roll
your own, one which has the chance to do a clean rollback of the
database, write an emergency backup of the user's text, or put a message
on the screen that the user can understand. Leaving this to assert() is
a disservice to the ordinary user.

Richard
Nov 14 '05 #12

P: n/a
In article <42**************@news.individual.net>,
rl*@hoekstra-uitgeverij.nl (Richard Bos) wrote:
CBFalconer <cb********@yahoo.com> wrote:
Michael Wojcik wrote:
Personally, I dislike assert and refrain from using it entirely; in
the time it takes me to insert an assertion, I can write a real, if
minimal, error handler which will do the right thing in both
development and production code.


But "quis custodes custodiens" <spelling?> applies. You vet your
data, and believe you have caught everything, thus routine foo will
never receive faulty parameters, and checking and correcting them
is not worth while. The assert in foo catches your faulty
thinking, and does no harm if you are correct. If triggered it
should tell the user "We goofed. Call Michael at 800-555-1212 and
tell him that <whatever> happened in foo", not "error 22".


No, if triggered assert() should print a message, usually cryptic and in
any case rarely adaptable, to stderr, where it is hardly ever even seen
by the user, and then crash the program. I'm with Michael here: check
your input before you use it, and if you need an error handler, roll
your own, one which has the chance to do a clean rollback of the
database, write an emergency backup of the user's text, or put a message
on the screen that the user can understand. Leaving this to assert() is
a disservice to the ordinary user.


Using assert as an error handler is just stupid. assert should be used
to catch bugs in your program - if the condition in the assert evaluates
to false, then you have a bug. Of course, if you think that some error
cannot occur, so you assert instead of handling it, and then the error
_does_ occur, then you have a bug, so the assert was correct in some
perverted way :-)
Nov 14 '05 #13

P: n/a
Christian Bau <ch***********@cbau.freeserve.co.uk> wrote:
In article <42**************@news.individual.net>,
rl*@hoekstra-uitgeverij.nl (Richard Bos) wrote:
No, if triggered assert() should print a message, usually cryptic and in
any case rarely adaptable, to stderr, where it is hardly ever even seen
by the user, and then crash the program. I'm with Michael here: check
your input before you use it, and if you need an error handler, roll
your own, one which has the chance to do a clean rollback of the
database, write an emergency backup of the user's text, or put a message
on the screen that the user can understand. Leaving this to assert() is
a disservice to the ordinary user.


Using assert as an error handler is just stupid. assert should be used
to catch bugs in your program - if the condition in the assert evaluates
to false, then you have a bug. Of course, if you think that some error
cannot occur, so you assert instead of handling it, and then the error
_does_ occur, then you have a bug, so the assert was correct in some
perverted way :-)


Correct, but still not useful. I find it very hard to debug when all
information I have is "My program just crashed. It said 'assertion
something', and then some numbers. No, I didn't write down the numbers."

Richard
Nov 14 '05 #14

P: n/a
"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
news:42**************@news.individual.net...
No, if triggered assert() should print a message, usually cryptic and in
any case rarely adaptable, to stderr, where it is hardly ever even seen
by the user, and then crash the program. I'm with Michael here: check
your input before you use it, and if you need an error handler, roll
your own, one which has the chance to do a clean rollback of the
database, write an emergency backup of the user's text, or put a message
on the screen that the user can understand. Leaving this to assert() is
a disservice to the ordinary user.


An "ordinary user" should never get a copy of your program with assert()s
enabled, so that's a moot point.

Nobody sane will argue against error-handling code. However, most of the
time error-handling code will silently "correct" the problem and continue on
without notifying anyone, so bugs don't get noticed. In debug builds of the
program, assert()s are useful because they make bugs obvious to
coders/testers, whose data is not important.

Another thing I've picked up over the years is to only use assert() for
_impossible_ conditions, not errors. For instance, if you have a function
that takes a pointer and is _documented_ to never accept NULL, then it's
perfectly valid for a _debug_ build to abort when it gets one. OTOH, a
non-debug build should handle the condition by doing something that makes
sense in context and doesn't crash/abort or otherwise lose user data.

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

Nov 14 '05 #15

P: n/a
Christian Bau wrote:
.... snip ...
Using assert as an error handler is just stupid. assert should be
used to catch bugs in your program - if the condition in the assert
evaluates to false, then you have a bug. Of course, if you think
that some error cannot occur, so you assert instead of handling it,
and then the error _does_ occur, then you have a bug, so the assert
was correct in some perverted way :-)


Exactly. There is no such thing as a proven bug free program. The
assert should always be redundant, at least in theory. If it
isn't, found one - lets stomp on it.

--
"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

Nov 14 '05 #16

P: n/a

In article <d1**********@nntp1.jpl.nasa.gov>, "E. Robert Tisdale" <E.**************@jpl.nasa.gov> writes:
Michael Wojcik wrote:
Personally, I dislike assert and refrain from using it entirely; in
the time it takes me to insert an assertion, I can write a real, if
minimal, error handler which will do the right thing in both
development and production code.
You still appear to be confused about the use of the assert macro.


I have never been confused about the use of the assert macro.
The assert macro is designed only to trap programming errors (bugs).
It's designed to abort a program if its parameter evaluates to zero.
You can't "handle" programming errors.
Perhaps you can't, but I certainly can.
What you call "errors" are more accurately described as *exceptions* --


There is nothing more "accurate" about the label "exception" in this
context.

You're as wrong as usual, Tisdale.

--
Michael Wojcik mi************@microfocus.com

Any average educated person can turn out competent verse. -- W. H. Auden
Nov 14 '05 #17

P: n/a

In article <mn***********************@YOURBRAnoos.fr>, "Emmanuel Delahaye" <em***@YOURBRAnoos.fr> writes:
Michael Wojcik wrote on 24/03/05 :
In article <mn***********************@YOURBRAnoos.fr>, "Emmanuel Delahaye"
<em***@YOURBRAnoos.fr> writes:
Rob Thorpe wrote on 23/03/05 :
In general, is it considered bad practice to use asserts in production
code?

You want CUnit.

http://cunit.sourceforge.net/
I'm curious why you think a unit-testing tool is relevant to the
question of whether to use asserts in production code.


Do you know this tool?


I haven't used it; I've glanced at the (minimal) documentation
provided on the project's home site and it's Sourceforge site.
Have you used the CU_ASSERT_xxx() macros
provided by the CUnit framework and library ?
No. Did I claim I had?
It gives another approach (mainly more detailed and subtle) of the use
of assertions macros.


Now there, you see, you began to answer my question. Why couldn't
you have provided this information (and, one might hope, something
substantial in addition) in your original post, rather than making
an opaque reference to something outside the standard with no
explanation?

--
Michael Wojcik mi************@microfocus.com

Advertising Copy in a Second Language Dept.:
The precious ovum itself is proof of the oath sworn to those who set
eyes upon Mokona: Your wishes will be granted if you are able to invest
it with eternal radiance... -- Noriyuki Zinguzi
Nov 14 '05 #18

P: n/a

In article <42***************@yahoo.com>, CBFalconer <cb********@yahoo.com> writes:
Michael Wojcik wrote:

Personally, I dislike assert and refrain from using it entirely; in
the time it takes me to insert an assertion, I can write a real, if
minimal, error handler which will do the right thing in both
development and production code.
But "quis custodes custodiens" <spelling?> applies. You vet your
data, and believe you have caught everything, thus routine foo will
never receive faulty parameters, and checking and correcting them
is not worth while.


No, I avoid this belief, and routine foo has parameter checks.

This is precisely my point: anywhere I might add an assertion, I can
*just as easily* add a real check and real error handling, and I do
so.
The assert in foo catches your faulty
thinking, and does no harm if you are correct.
The real error handling does no harm if I am incorrect, either,
unlike the assert macro.
If triggered it
should tell the user "We goofed. Call Michael at 800-555-1212 and
tell him that <whatever> happened in foo", not "error 22".


And how, in portable C, is this to be achieved with the assert macro?

--
Michael Wojcik mi************@microfocus.com

Do not "test" parts, as this may compromise sensitive joinery. Those who
suffer difficulty should abandon the enterprise immediately. -- Chris Ware
Nov 14 '05 #19

P: n/a
Stephen Sprunk wrote:
.... snip ...
Another thing I've picked up over the years is to only use assert()
for _impossible_ conditions, not errors. For instance, if you have
a function that takes a pointer and is _documented_ to never accept
NULL, then it's perfectly valid for a _debug_ build to abort when
it gets one. OTOH, a non-debug build should handle the condition
by doing something that makes sense in context and doesn't
crash/abort or otherwise lose user data.


Agreed, but you omit some necessary areas. You simply can't ensure
such 'safe' operation, because the library portions will crash.
You can't use a NULL FILE* to fread, or a NULL char * to strlen,
for example. So you normally attempt to prevent these from arising
early on, by putting the check right at the fopen, or malloc, for
example. However some people get sloppy, and don't install those
checks at first writing. I know it isn't you, but you do have
sloppy apprentices and helpers, don't you? So somewhere along the
line you think you have put all those checks in, and can turn off
the assert. Guess again.

There remains a rarely executed path, that nobody followed, and
that it takes an ingenious fool to trigger. It leads to UB and
heavy loss of data, but no crash. The customer is irate, and you
haven't the vaguest idea what happened. The ingenious fool only
did it by accident, because his girl friend called and mentioned
pregnancy during data entry.

If you had left the assert there would have been a message and a
clue, the heavy data loss wouldn't have occured (after all, you did
allow for power failures and so forth), and the customer, while
still irate, could be reasoned with.

This is why I try to define as much behaviour as possible in my
routines. For example I have been criticized for having my strlcpy
and strlcat versions interpret NULL input (but not output)
parameters as empty strings. My attitude is if you want to check
against NULL, do so before calling. The routine is intended to
work in production, not to rub your nose in your own misdeeds. The
C library that I use here will, when asked to printf a NULL string,
write out "{null}" instead of crashing. That has been known to
give me a clue as to my own misdeeds.

Crashes are bad. Crashes are better than data destruction.
Crashes with messages and no data destruction are better yet. Data
destruction is especially bad, and this includes recording
erroneous data. Some programmers are fallible (even I).

--
"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
Nov 14 '05 #20

P: n/a


Michael Wojcik wrote:
CBFalconer <cb********@yahoo.com> writes:
If triggered it
should tell the user "We goofed. Call Michael at 800-555-1212 and
tell him that <whatever> happened in foo", not "error 22".

And how, in portable C, is this to be achieved with the assert macro?


tardis 105 =>cat foo.c
#include <assert.h>
int main(void) {
#line 42 "We goofed. Call Michael at 800-555-1212."
assert(0);
return 0;
}
tardis 106 =>cc foo.c
tardis 107 =>./a.out
Assertion failed: 0, file We goofed. Call Michael at 800-555-1212., line 42
Abort
tardis 108 =>

--
Er*********@sun.com

Nov 14 '05 #21

P: n/a
Michael Wojcik wrote on 25/03/05 :
The assert macro is designed only to trap programming errors (bugs).


It's designed to abort a program if its parameter evaluates to zero.


What ? Sounds to be a narrow mind approach, doesn't it ?

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"C is a sharp tool"

Nov 14 '05 #22

P: n/a
Michael Wojcik wrote:
CBFalconer <cb********@yahoo.com> writes:
.... snip ...
If triggered it
should tell the user "We goofed. Call Michael at 800-555-1212 and
tell him that <whatever> happened in foo", not "error 22".


And how, in portable C, is this to be achieved with the assert macro?


How about:

assert(p = "Message", logical_statement);

The point is you 'know' it can never be triggered. Then it costs
nothing to leave it in, assuming it is not a performance hog. If
you expect it to ever be triggered, then I agree with you whole
heartedly.

--
"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
Nov 14 '05 #23

P: n/a
In article <42***************@news.individual.net>,
rl*@hoekstra-uitgeverij.nl (Richard Bos) wrote:
Christian Bau <ch***********@cbau.freeserve.co.uk> wrote:
In article <42**************@news.individual.net>,
rl*@hoekstra-uitgeverij.nl (Richard Bos) wrote:
No, if triggered assert() should print a message, usually cryptic and in
any case rarely adaptable, to stderr, where it is hardly ever even seen
by the user, and then crash the program. I'm with Michael here: check
your input before you use it, and if you need an error handler, roll
your own, one which has the chance to do a clean rollback of the
database, write an emergency backup of the user's text, or put a message
on the screen that the user can understand. Leaving this to assert() is
a disservice to the ordinary user.


Using assert as an error handler is just stupid. assert should be used
to catch bugs in your program - if the condition in the assert evaluates
to false, then you have a bug. Of course, if you think that some error
cannot occur, so you assert instead of handling it, and then the error
_does_ occur, then you have a bug, so the assert was correct in some
perverted way :-)


Correct, but still not useful. I find it very hard to debug when all
information I have is "My program just crashed. It said 'assertion
something', and then some numbers. No, I didn't write down the numbers."


In production code, the only purpose of an assert is to stop the program
from running when there is trouble. So you leave asserts in if you think
it is better that your program is stopped by an assert then leaving it
running and risking all kinds of horrible things to happen.

That is a judgement call. In some situations the assert will do more
damage; in some cases removing the assert will do more damage. Depends
on what your program does.

(There is another rare possibility: That the assert actually fixes the
problem. I have _once_ seen code where someone wrote "assert (x = 1);"
by accident instead of "assert (x == 1);". The weird thing was that x
was actually zero at that point, which was a bug, and setting it to 1
fixed the bug. Program crashed when asserts were removed).
Nov 14 '05 #24

P: n/a


CBFalconer wrote:
Michael Wojcik wrote:
CBFalconer <cb********@yahoo.com> writes:


... snip ...
If triggered it
should tell the user "We goofed. Call Michael at 800-555-1212 and
tell him that <whatever> happened in foo", not "error 22".


And how, in portable C, is this to be achieved with the assert macro?

How about:

assert(p = "Message", logical_statement);


assert( (p = "Message", logical_expression) );

--
Er*********@sun.com

Nov 14 '05 #25

P: n/a
Richard Bos wrote:
[---]
Correct, but still not useful. I find it very hard to debug when all
information I have is "My program just crashed. It said 'assertion
something', and then some numbers. No, I didn't write down the numbers."


I have never used assert to actually "debug" (I'm getting into
semantics here). I use assert to identify that a problem has occured,
and thanks to it telling me where the problem occured, I know _where_ to
debug. Asserts have, to me, proved quite unhelpful when I'm working with
someone elses code, but for my own it's always been a nifty tool (since
when they occur, you have a pretty good idea about what could have gone
wrong).

IMHO, if someone is thinking that assert() is about replacing a
debug_print()-routine, then that someone does not understand how to
properly make use of assert().

--
Kind regards,
Jan Danielsson
Nobody loves a cynic
Nov 14 '05 #26

P: n/a
CBFalconer <cb********@yahoo.com> wrote in message news:<42***************@yahoo.com>...
Michael Wojcik wrote:
Christian Bau <ch***********@cbau.freeserve.co.uk> writes:

I would very much hope that your production code doesn't contain
any "commonly encountered errors".


Code does not have to "contain ... commonly encountered errors" in
order to encounter them. It must account for erroneous input,
failures in the implementation (such as memory allocation failure),
and so forth. Those things could be, and are, sometimes trapped with
asserts in development code; Rob, I believe, is correctly noting that
they should not be handled by assert in production code.

My production code is full of error checking, and some of those
branches are not uncommonly taken (for sufficiently generous values
of "common").

Personally, I dislike assert and refrain from using it entirely; in
the time it takes me to insert an assertion, I can write a real, if
minimal, error handler which will do the right thing in both
development and production code.


But "quis custodes custodiens" <spelling?> applies. You vet your
data, and believe you have caught everything, thus routine foo will
never receive faulty parameters, and checking and correcting them
is not worth while. The assert in foo catches your faulty
thinking, and does no harm if you are correct. If triggered it
should tell the user "We goofed. Call Michael at 800-555-1212 and
tell him that <whatever> happened in foo", not "error 22".


This was exactly what I was thinking about.

I've written a program where data comes in from a set of sources. If
one of a set of values in the program are larger than 10000000 then it
will fail. So, everywhere the data enters it is checked to make sure
it is less than that number.

By the time the values have reached the subroutine where they're used
they cannot be incorrect. But it seems useful to check again at this
stage again, I lose nothing by doing so. If I have in fact checked
the code correctly then nothing is wrong, if I haven't then at least a
moderately useful error message appears to the user. I can't use a
normal error check, because if the subroutine recieves an incorrect
value then everything else in the program screwed anyway, so aborting
makes sense.

So, what seems logical to me is to put something similar to an assert
in. But without disabling it in the users version of the software.
The function I wrote does a little more than assert, to make it more
informative.
Nov 14 '05 #27

P: n/a
"Emmanuel Delahaye" <em***@YOURBRAnoos.fr> wrote:
Michael Wojcik wrote on 25/03/05 :
The assert macro is designed only to trap programming errors (bugs).


It's designed to abort a program if its parameter evaluates to zero.


What ? Sounds to be a narrow mind approach, doesn't it ?


It's exactly what the Standard says. Print a message where the end user
probably won't notice it, then abort without a by-your-leave.

Richard
Nov 14 '05 #28

P: n/a
"Stephen Sprunk" <st*****@sprunk.org> wrote:
"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
news:42**************@news.individual.net...
No, if triggered assert() should print a message, usually cryptic and in
any case rarely adaptable, to stderr, where it is hardly ever even seen
by the user, and then crash the program. I'm with Michael here: check
your input before you use it, and if you need an error handler, roll
your own, one which has the chance to do a clean rollback of the
database, write an emergency backup of the user's text, or put a message
on the screen that the user can understand. Leaving this to assert() is
a disservice to the ordinary user.


An "ordinary user" should never get a copy of your program with assert()s
enabled, so that's a moot point.


No, that is my entire point. assert() is _not_ useful for the finished
product, only for in-house debugging. For anything your user sees (or
even, heaven forbid, uses!), you need a more user-friendly (not to
mention support-desk-friendly) assertion mechanism.

Richard
Nov 14 '05 #29

P: n/a
"CBFalconer" <cb********@yahoo.com> wrote in message
news:42***************@yahoo.com...
Stephen Sprunk wrote:
Another thing I've picked up over the years is to only use
assert() for _impossible_ conditions, not errors. For instance,
if you have a function that takes a pointer and is _documented_
to never accept NULL, then it's perfectly valid for a _debug_
build to abort when it gets one. OTOH, a non-debug build
should handle the condition by doing something that makes
sense in context and doesn't crash/abort or otherwise lose
user data.
Agreed, but you omit some necessary areas. You simply can't
ensure such 'safe' operation, because the library portions will crash.
You can't use a NULL FILE* to fread, or a NULL char * to strlen,
for example. So you normally attempt to prevent these from arising
early on, by putting the check right at the fopen, or malloc, for
example. However some people get sloppy, and don't install those
checks at first writing. I know it isn't you, but you do have
sloppy apprentices and helpers, don't you? So somewhere along the
line you think you have put all those checks in, and can turn off
the assert. Guess again.


If I put an assert() in my code, then I also put in error handling code
right after it for the same condition. The sloppy coders that come after me
will hopefully learn from that example; the ones that don't wouldn't think
to assert() in the first place.
This is why I try to define as much behaviour as possible in my
routines. For example I have been criticized for having my strlcpy
and strlcat versions interpret NULL input (but not output)
parameters as empty strings. My attitude is if you want to check
against NULL, do so before calling. The routine is intended to
work in production, not to rub your nose in your own misdeeds. The
C library that I use here will, when asked to printf a NULL string,
write out "{null}" instead of crashing. That has been known to
give me a clue as to my own misdeeds.
If I were writing the same functions, I would assert() the arguments aren't
NULL but non-debug versions would do something similar to what you describe.
I'd still document the functions as not accepting NULL if only because
strcpy() and strcat() don't define corresponding behavior.
Crashes are bad. Crashes are better than data destruction.
Crashes with messages and no data destruction are better yet. Data
destruction is especially bad, and this includes recording
erroneous data. Some programmers are fallible (even I).


Agreed. I don't write perfect code, but I find aborting on errors focuses
my debugging better than silently handling them.

S
Nov 14 '05 #30

P: n/a
Rob Thorpe wrote:
In general,
is it considered bad practice to use asserts in production code?

What about writing a macro that does the same as assert
but continues to work regardless of the state of NDEBUG?
Suppose that you are writing a function library
for other C programmers to use with a function

double sqrt(double);

for example,
and your Application Program Interface (API) specifies that
it is a programming error to pass a negative value to sqrt(double).
You can help programmers who use your library
to trap and locate this bug:
cat library.h

#ifndef GUARD_LIBRARY_H
#define GUARD_LIBRARY_H 1
#include<math.h>

inline
double sqrt_error(double x, char* file, int line) {
if (x < 0.0) {
fprintf(stderr, "In file %s: line #%d: "
"argument 1 in function sqrt(double) is negative!",
file, line);
}
return sqrt(x);
}

#ifndef NDEBUG
#define sqrt(x) sqrt_error((x), __FILE__, __LINE__)
#endif//NDEBUG

#endif//GUARD_LIBRARY_H

Unless NDEBUG is defined,
every invocation of sqrt(x) will be replaced
with sqrt_error((x), __FILE__, __LINE__)
and sqrt_error(double, char*, int) will report
the file name and line number where the bug occurred.
Nov 14 '05 #31

P: n/a

In article <mn***********************@YOURBRAnoos.fr>, "Emmanuel Delahaye" <em***@YOURBRAnoos.fr> writes:
Michael Wojcik wrote on 25/03/05 :
The assert macro is designed only to trap programming errors (bugs).


It's designed to abort a program if its parameter evaluates to zero.


What ? Sounds to be a narrow mind approach, doesn't it ?


Perhaps it is. I didn't design it; I'm merely noting what it was
designed to do.

Perhaps you mean the assert macro is *intended* to be used "only to
trap programming errors". I can't speak to its author's intentions,
and frankly I don't particularly care what they were. We have the
assert macro; it does a certain thing; I don't feel that thing is
useful. It could have been intended to bring peace and joy to the
whole wide world, for all I care - that still doesn't make it useful
in my opinion.

I'll reiterate my position: it does not take significantly more effort
to write a proper error handler than it does to write an assertion.

--
Michael Wojcik mi************@microfocus.com

You brung in them two expert birdwatchers ... sayin' it was to keep us from
makin' dern fools of ourselfs ... whereas it's the inherent right of all to
make dern fools of theirselfs ... it ain't a right held by you official types
alone. -- Walt Kelly
Nov 14 '05 #32

P: n/a

In article <d2**********@news1brm.Central.Sun.COM>, Eric Sosman <er*********@sun.com> writes:
Michael Wojcik wrote:
CBFalconer <cb********@yahoo.com> writes:
If triggered it
should tell the user "We goofed. Call Michael at 800-555-1212 and
tell him that <whatever> happened in foo", not "error 22".


And how, in portable C, is this to be achieved with the assert macro?


#line 42 "We goofed. Call Michael at 800-555-1212."
assert(0);


Fair enough, albeit rather pointless. I hope that wasn't what CBF
had in mind.

--
Michael Wojcik mi************@microfocus.com
Nov 14 '05 #33

P: n/a

In article <42***************@yahoo.com>, CBFalconer <cb********@yahoo.com> writes:
How about:

assert(p = "Message", logical_statement);

The point is you 'know' it can never be triggered. Then it costs
nothing to leave it in, assuming it is not a performance hog. If
you expect it to ever be triggered, then I agree with you whole
heartedly.


But *my* point is that regardless of whether I expect the error
path to be followed (and I never expect any error path is impossible;
transient memory errors do occur, after all), it costs me no more to
put in proper error handling than it would cost me to put in an
assertion.

What does the assertion buy you that proper error handling does not?
The assertion is not generated automatically - C doesn't come with
built-in Design-by-Contract. The programmer either decides to put in
some form of input validation, or decides not to. In the former case
it might as well be something better than assert. In the latter any
usefulness of assert is moot, because there won't be an assert there
either. In neither case is the use of assert justified.

--
Michael Wojcik mi************@microfocus.com

Most people believe that anything that is true is true for a reason.
These theorems show that some things are true for no reason at all,
i.e., accidentally, or at random. -- G J Chaitin
Nov 14 '05 #34

P: n/a

In article <d2**********@news1brm.Central.Sun.COM>, Eric Sosman <er*********@sun.com> writes:
CBFalconer wrote:
Michael Wojcik wrote:
CBFalconer <cb********@yahoo.com> writes:
If triggered it
should tell the user "We goofed. Call Michael at 800-555-1212 and
tell him that <whatever> happened in foo", not "error 22".

And how, in portable C, is this to be achieved with the assert macro?


How about:

assert(p = "Message", logical_statement);


assert( (p = "Message", logical_expression) );


Is the "p =" even necessary? I don't see anything wrong with just
having "Message" stand alone as the LHS of the comma operator. It's
just an expression with no side effects. I guess

"Message" && logical_expression

would work as well, for that matter, and dispense with the extra
parentheses in the bargain. Or

logical_expression? "Message" : 0

I'm sure there are other torturous ways of achieving with the assert
macro something that could be done much more elegantly without it.

Perhaps from now on I'll wrap every single line of code in an assert
macro, using the logical-negation and comma operators to force results
to the right value, so that when an error occurs I'll know just what
line was the problem. Who needs debuggers?

--
Michael Wojcik mi************@microfocus.com

I do not care to listen; obloquy injures my self-esteem and I am
skeptical of praise. -- Jack Vance
Nov 14 '05 #35

P: n/a
Michael Wojcik wrote:
CBFalconer <cb********@yahoo.com> writes:
How about:

assert(p = "Message", logical_statement);

The point is you 'know' it can never be triggered. Then it costs
nothing to leave it in, assuming it is not a performance hog. If
you expect it to ever be triggered, then I agree with you whole
heartedly.


But *my* point is that regardless of whether I expect the error
path to be followed (and I never expect any error path is
impossible; transient memory errors do occur, after all), it costs
me no more to put in proper error handling than it would cost me
to put in an assertion.

What does the assertion buy you that proper error handling does
not? The assertion is not generated automatically - C doesn't come
with built-in Design-by-Contract. The programmer either decides
to put in some form of input validation, or decides not to. In
the former case it might as well be something better than assert.
In the latter any usefulness of assert is moot, because there
won't be an assert there either. In neither case is the use of
assert justified.


You have already done the proper error handling (you thought) up
front where you knew how to handle it. This assert is deep in the
bowels, and the routine has no idea what to do next. If it ever
gets triggered you know you goofed somewhere, and you may get a
clue as to where. Sure, it would be preferable to have handled it
properly in the proper place, but you didn't, did you? Meanwhile
it has saved your long-suffering user from the destruction of his
data over the past 20 years. You and Dan Pop may be infallible,
but I suspect that I'm not.

--
"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
Nov 14 '05 #36

P: n/a
mw*****@newsguy.com (Michael Wojcik) writes:
In article <d2**********@news1brm.Central.Sun.COM>, Eric Sosman
<er*********@sun.com> writes:
Michael Wojcik wrote:
> CBFalconer <cb********@yahoo.com> writes:
>
>>If triggered it
>>should tell the user "We goofed. Call Michael at 800-555-1212 and
>>tell him that <whatever> happened in foo", not "error 22".
>
> And how, in portable C, is this to be achieved with the assert macro?


#line 42 "We goofed. Call Michael at 800-555-1212."
assert(0);


Fair enough, albeit rather pointless. I hope that wasn't what CBF
had in mind.


I wouldn't call it pointless (unless you mean that the message should
have been in the argument to assert(), or to some better error
handling routine), but it does clobber the line number and file name,
which could mess up other diagnostics.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <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.
Nov 14 '05 #37

P: n/a
In article <d2********@news3.newsguy.com>,
mw*****@newsguy.com (Michael Wojcik) wrote:
In article <42***************@yahoo.com>, CBFalconer <cb********@yahoo.com>
writes:
How about:

assert(p = "Message", logical_statement);

The point is you 'know' it can never be triggered. Then it costs
nothing to leave it in, assuming it is not a performance hog. If
you expect it to ever be triggered, then I agree with you whole
heartedly.


But *my* point is that regardless of whether I expect the error
path to be followed (and I never expect any error path is impossible;
transient memory errors do occur, after all), it costs me no more to
put in proper error handling than it would cost me to put in an
assertion.

What does the assertion buy you that proper error handling does not?
The assertion is not generated automatically - C doesn't come with
built-in Design-by-Contract. The programmer either decides to put in
some form of input validation, or decides not to. In the former case
it might as well be something better than assert. In the latter any
usefulness of assert is moot, because there won't be an assert there
either. In neither case is the use of assert justified.


assert should be used to find bugs in your program. Example:

for (i = 0; i < n; ++i) a [i] = 0;
assert (i >= n && (n < 0 || i == n));

After execution of the loop, i will be equal to n, except if n was
negative. There will be no assertion unless I made some mistake in this
tiny bit of code. If I made a mistake, then how could I possibly handle
it? If I knew that there is a bug in the code and which bug, then I
would fix it. But I believe there is no bug, and I have no idea how to
handle it if there was one.

Incorrect inputs are not bugs in the program and therefore should never
be handled by an assert.
Nov 14 '05 #38

P: n/a

In article <ln************@nuthaus.mib.org>, Keith Thompson <ks***@mib.org> writes:
mw*****@newsguy.com (Michael Wojcik) writes:
In article <d2**********@news1brm.Central.Sun.COM>, Eric Sosman
<er*********@sun.com> writes:

#line 42 "We goofed. Call Michael at 800-555-1212."
assert(0);
Fair enough, albeit rather pointless. I hope that wasn't what CBF
had in mind.


I wouldn't call it pointless (unless you mean that the message should
have been in the argument to assert(), or to some better error
handling routine),


That is indeed what I meant, since:
but it does clobber the line number and file name,
which could mess up other diagnostics.


makes it an extremely poor choice. It's also fragile, since there's
nothing preventing the programmer from using the same arguments for
#line in another location.

--
Michael Wojcik mi************@microfocus.com

There are many definitions of what art is, but what I am convinced art is not
is self-expression. If I have an experience, it is not important because it
is mine. It is important because it's worth writing about for other people,
worth sharing with other people. That is what gives it validity. (Auden)
Nov 14 '05 #39

P: n/a

In article <42***************@yahoo.com>, CBFalconer <cb********@yahoo.com> writes:
Michael Wojcik wrote:
CBFalconer <cb********@yahoo.com> writes:
How about:

assert(p = "Message", logical_statement);

The point is you 'know' it can never be triggered.
But *my* point is that regardless of whether I expect the error
path to be followed (and I never expect any error path is
impossible; transient memory errors do occur, after all), it costs
me no more to put in proper error handling than it would cost me
to put in an assertion.


You have already done the proper error handling (you thought) up
front where you knew how to handle it. This assert is deep in the
bowels, and the routine has no idea what to do next.


How many times do I have to say this? I PUT THE ERROR CHECKS IN
THE LOW-LEVEL ROUTINES AS WELL. THEY AREN'T ANY MORE WORK THAN
AN assert WOULD BE.
If it ever
gets triggered you know you goofed somewhere, and you may get a
clue as to where. Sure, it would be preferable to have handled it
properly in the proper place, but you didn't, did you? Meanwhile
it has saved your long-suffering user from the destruction of his
data over the past 20 years. You and Dan Pop may be infallible,
but I suspect that I'm not.


I *know* I'm not, which is why I put the damn error checks in every
function. I have never claimed that it was better to leave all
validation out; I have been claiming that it's better to put in
real error handling than to use assert.

--
Michael Wojcik mi************@microfocus.com

Vinegar keeps more flies away than honey does.
Nov 14 '05 #40

P: n/a

In article <ch*********************************@slb-newsm1.svr.pol.co.uk>, Christian Bau <ch***********@cbau.freeserve.co.uk> writes:
In article <d2********@news3.newsguy.com>,
mw*****@newsguy.com (Michael Wojcik) wrote:
But *my* point is that regardless of whether I expect the error
path to be followed (and I never expect any error path is impossible;
transient memory errors do occur, after all), it costs me no more to
put in proper error handling than it would cost me to put in an
assertion.

What does the assertion buy you that proper error handling does not?
The assertion is not generated automatically - C doesn't come with
built-in Design-by-Contract. The programmer either decides to put in
some form of input validation, or decides not to. In the former case
it might as well be something better than assert. In the latter any
usefulness of assert is moot, because there won't be an assert there
either. In neither case is the use of assert justified.
assert should be used to find bugs in your program.


My point is precisely that no, it shouldn't, because it's a terrible
error-handling mechanism. It provides no recovery and poor reporting.
Example:
for (i = 0; i < n; ++i) a [i] = 0;
assert (i >= n && (n < 0 || i == n));

After execution of the loop, i will be equal to n, except if n was
negative. There will be no assertion unless I made some mistake in this
tiny bit of code. If I made a mistake, then how could I possibly handle
it?
By logging the problem, using the program's logging mechanism (which
could be trivial, if it's a trivial program, or complex if it isn't),
and returning an error to the caller.
Incorrect inputs are not bugs in the program and therefore should never
be handled by an assert.


True, but too narrow. Nothing should ever be "handled" by assert,
because it's an astoundingly poor way of "handling" things.

And please note that in this thread Chuck and I were both discussing
incorrect input to low-level functions, which could very well be bugs
in the program (such as passing a null pointer to a function which
requires a non-null one).

--
Michael Wojcik mi************@microfocus.com

If Mokona means for us to eat this, I, a gentle person, will become
angry! -- Umi (CLAMP & unknown translator), _Magic Knight Rayearth_
Nov 14 '05 #41

P: n/a
Rob Thorpe wrote:

In general, is it considered bad practice to use asserts in production
code?


I only use assert to make sure that any macros
which are intended to be readily changeable by the programmer,
retain valid values.

--
pete
Nov 14 '05 #42

P: n/a
Richard Bos wrote:

Correct, but still not useful. I find it very hard to debug when all
information I have is "My program just crashed. It said 'assertion
something', and then some numbers. No, I didn't write down the numbers."

Richard


The numbers aren't meaningless. Presumably you put the assert statement
there in the first place because you thought you might have a bug at
line number xxxx. The assert message will tell you that yes, by golly,
something IS happening at line xxxx that isn't kosher. Personally, I
would find that useful for debugging and I would distinguish it from
code that is intended, for example, to check whether input can be
processed appropriately and "handle" it if it can't be.

-JS
Nov 14 '05 #43

P: n/a
On Thu, 31 Mar 2005 23:19:58 GMT, John Smith
<JS****@mail.net> wrote:
Richard Bos wrote:

Correct, but still not useful. I find it very hard to debug when all
information I have is "My program just crashed. It said 'assertion
something', and then some numbers. No, I didn't write down the numbers."


The numbers aren't meaningless. Presumably you put the assert statement
there in the first place because you thought you might have a bug at
line number xxxx. The assert message will tell you that yes, by golly,
something IS happening at line xxxx that isn't kosher. Personally, I
would find that useful for debugging and I would distinguish it from
code that is intended, for example, to check whether input can be
processed appropriately and "handle" it if it can't be.


But how do you know what the actual value was that caused the assert to
fail? That information can be very useful in tracking the bug, whereas
"something's wrong at line 3456" doesn't tell you anything at all about
the data.

assert(x <= 10);

traps the error, but doesn't tell you whether x is 11 or 2147483647.

It's also difficult with a source debugger to insert a breakpoint where
the error has occurred, whereas:

#ifndef NDEBUG
if (x > 10)
{
do_log(LOG_ERROR, "x (%d) > 10\n", x);
abort();
}
#endif

not only logs the information but also provides a handy place to put a
breakpoint so that you can trace the stack or whatever.

Chris C
Nov 14 '05 #44

P: n/a
Chris Croughton wrote:
On Thu, 31 Mar 2005 23:19:58 GMT, John Smith
<JS****@mail.net> wrote:

Richard Bos wrote:
Correct, but still not useful. I find it very hard to debug when all
information I have is "My program just crashed. It said 'assertion
something', and then some numbers. No, I didn't write down the numbers."
The numbers aren't meaningless. Presumably you put the assert statement
there in the first place because you thought you might have a bug at
line number xxxx. The assert message will tell you that yes, by golly,
something IS happening at line xxxx that isn't kosher. Personally, I
would find that useful for debugging and I would distinguish it from
code that is intended, for example, to check whether input can be
processed appropriately and "handle" it if it can't be.

But how do you know what the actual value was that caused the assert to
fail? That information can be very useful in tracking the bug, whereas
"something's wrong at line 3456" doesn't tell you anything at all about
the data.


Before you can start looking at erroneous values you have to know where
they occur.
assert(x <= 10);

traps the error, but doesn't tell you whether x is 11 or 2147483647.
printf("x: %d\n", x); /* I know some people hate this kind of thing */

It's also difficult with a source debugger to insert a breakpoint where
the error has occurred, whereas:

#ifndef NDEBUG
if (x > 10)
{
do_log(LOG_ERROR, "x (%d) > 10\n", x);
abort();
}
#endif
This is perfectly fine, if you don't mind writing seven lines of code
instead of one (not including, of course, the implementation of do_log).
not only logs the information but also provides a handy place to put a
breakpoint so that you can trace the stack or whatever.

Chris C

Nov 14 '05 #45

P: n/a
Chris Croughton wrote:
[---]
But how do you know what the actual value was that caused the assert to
fail? That information can be very useful in tracking the bug, whereas
"something's wrong at line 3456" doesn't tell you anything at all about
the data.

assert(x <= 10);

traps the error, but doesn't tell you whether x is 11 or 2147483647.
Obviously, knowing the value isn't relevant when you use assert(),
because if it was, then you're probably not going to use assert().
Asserts are meant to abort the application and tell you where it
aborted. No more, no less. If you want it to output something more, then
don't use assert().

When an assert() has aborted the program, that means that there's no
point in continuing execution - because something had gone very wrong.
Because it is an assert(), it's obvious from the context what went wrong
(or rather, it's obvious where the application needs to be debugged). If
it's not, you're using asserts wrong (IMHO).
It's also difficult with a source debugger to insert a breakpoint where
the error has occurred, whereas:

#ifndef NDEBUG
if (x > 10)
{
do_log(LOG_ERROR, "x (%d) > 10\n", x);
abort();
}
#endif

not only logs the information but also provides a handy place to put a
breakpoint so that you can trace the stack or whatever.


That would assume that the value of x is interresting. It's not
always. When it is, you output it before terminating. If it's not
interresting, then why not just use assert()?

It seems that some of those advocating against assert() think that
you either use one or the other method, and that's impossible to mix
them. In my fatal error management code, I have in the area of 5%
assert() calls, and the rest calls which look much like your snippet
above. Sometimes, it's just a waste of time and space to use anything
more than assert().

--
Kind regards,
Jan Danielsson
Nobody loves a cynic
Nov 14 '05 #46

P: n/a
John Smith <JS****@mail.net> wrote:
Richard Bos wrote:

Correct, but still not useful. I find it very hard to debug when all
information I have is "My program just crashed. It said 'assertion
something', and then some numbers. No, I didn't write down the numbers."


The numbers aren't meaningless.


Not to the programmer. To the average user, though, an assert() warning
might as well have been in Proto-Elamite; and good luck trying to get
dependable line numbers out of them.

Richard
Nov 14 '05 #47

P: n/a
# Not to the programmer. To the average user, though, an assert() warning
# might as well have been in Proto-Elamite; and good luck trying to get
# dependable line numbers out of them.

It's far better to run production code with no checking to give user the false
impression that all is well, rather than giving them some hint there is a
problem and they need help.

--
SM Ryan http://www.rawbw.com/~wyrmwif/
Where do you get those wonderful toys?
Nov 14 '05 #48

This discussion thread is closed

Replies have been disabled for this discussion.