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

How does assert benefit your code really?

P: n/a
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

Apr 11 '06 #1
Share this Question
Share on Google+
28 Replies


P: n/a

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

Apr 11 '06 #2

P: n/a
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>
Apr 11 '06 #3

P: n/a
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.

Apr 11 '06 #4

P: n/a
"lovecreatesbeauty" <lo***************@gmail.com> 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
Apr 11 '06 #5

P: n/a
John Devereux wrote:
"lovecreatesbeauty" <lo***************@gmail.com> 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*
==============
Apr 11 '06 #6

P: n/a
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.
Apr 11 '06 #7

P: n/a
On 2006-04-11, Kiru Sengal <ki*********@gmail.com> 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
Apr 11 '06 #8

P: n/a
Ian Collins <ia******@hotmail.com> 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
Apr 11 '06 #9

P: n/a
"Manuel Tobias Schiller" <ma**@hinterbergen.de> wrote in message
news:sl*****************@ws02.hinter.bergen...
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 ***
Apr 11 '06 #10

P: n/a
Stephen Sprunk wrote:
"Manuel Tobias Schiller" <ma**@hinterbergen.de> wrote in message
news:sl*****************@ws02.hinter.bergen...
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.
Apr 11 '06 #11

P: n/a
John Devereux wrote:
Ian Collins <ia******@hotmail.com> 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.
Apr 11 '06 #12

P: n/a
Ian Collins <ia******@hotmail.com> writes:
John Devereux wrote:
Ian Collins <ia******@hotmail.com> 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
Apr 11 '06 #13

P: n/a
"Stephen Sprunk" <st*****@sprunk.org> 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) 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.
Apr 11 '06 #14

P: n/a
John Devereux wrote:
Ian Collins <ia******@hotmail.com> writes:

John Devereux wrote:
Ian Collins <ia******@hotmail.com> 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.
Apr 12 '06 #15

P: n/a
Manuel Tobias Schiller wrote:
On 2006-04-11, Kiru Sengal <ki*********@gmail.com> 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/>
Apr 12 '06 #16

P: n/a
CBFalconer wrote:
Manuel Tobias Schiller wrote:
On 2006-04-11, Kiru Sengal <ki*********@gmail.com> 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.
Apr 12 '06 #17

P: n/a
Ian Collins <ia******@hotmail.com> writes:
CBFalconer wrote:
Manuel Tobias Schiller wrote:
On 2006-04-11, Kiru Sengal <ki*********@gmail.com> 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) 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.
Apr 12 '06 #18

P: n/a

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.

Apr 12 '06 #19

P: n/a
Keith Thompson schrieb:
Ian Collins <ia******@hotmail.com> writes:
CBFalconer wrote:
Manuel Tobias Schiller wrote:
On 2006-04-11, Kiru Sengal <ki*********@gmail.com> 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.
Apr 12 '06 #20

P: n/a
pinkfog wrote:
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.

No try_catch in C!

--
Ian Collins.
Apr 12 '06 #21

P: n/a
Le 11-04-2006, lovecreatesbeauty <lo***************@gmail.com> a écrit*:
" 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?


To me, there are 3 differents uses of assert:

1) debuging
When debuging/developping, assert ensures that the logic of
your code is respected.
double get(Vector v, size_t index){
assert( index < size(v) ):
...
}

2) unitary tests
If you do not have a efficient framework for
unitary tests, assert is usefull.

void test_Vector(){
Vector v;
init(&v);
assert( size(v) == 0 );
add(&v, 1.0 );
assert( get(v,0) == 1.0 );
...
}

3) run-time error
The question of run-time errors is huge. In fact, assert
is only a mecanism, and your code should have a politic.
(Notice that bad user input or ressource lack is not a
"run time error").

It depends on your code: in embeded systems, sometime,
the better is to log the error and to reset. Then, assert
can be redefinied as log + reset. In an aplication done
for a home user with GUI, assert is not very user-friendly
solution. In a banking system, if a very strange thing occurs,
is it better to shut-down the system or to let the strange
thing occurs and to log it ? There is no general solution.
It depend.

One benefit of assert is that it is a macro. So, you should
associates differents behaviors to assert depending on
your politic.

At least, assert is often better than no error checking.
Its better to know that the code crashed with message
'assertion failed in toto.c:134' than it crashed when
the user sometime clicks on 'Save' button.
Marc Boyer
Apr 12 '06 #22

P: n/a
On 2006-04-11, CBFalconer <cb********@yahoo.com> wrote:
Manuel Tobias Schiller wrote:
On 2006-04-11, Kiru Sengal <ki*********@gmail.com> wrote:
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 agree that ordinary user errors (wrong parameters/incorrect usage
etc.) should be handled with a decent error message on stderr. However,
catching things that "can't" happen with assert might be a good idea; in
my case, a user had set up his spooling system so strangely that it fed
valid input to my driver, however a 100 by 100 pixel wide input for an
A4 page at 600 dpi is ridiculous (and points to wrong usage of the other
filters in the print data filtering chain), and these small dimensions
triggered an "unthought-of" bug in the code that enforced page margins.
Having my printer filter abort with an assert is in this case better
then silently ignoring the issue, because one might damage hardware
otherwise.

Regards.

Manuel
--
Homepage: http://www.hinterbergen.de/mala
OpenPGP: 0xA330353E (DSA) or 0xD87D188C (RSA)
Apr 12 '06 #23

P: n/a
On Wed, 12 Apr 2006 09:12:56 +0000, Manuel Tobias Schiller
<ma**@hinterbergen.de> wrote:
Having my printer filter abort with an assert is in this case better
then silently ignoring the issue


Why are those the only two options?

Surely you could replace the assert with an orderly shutdown in a
manner less frightening (and more informative) for the user.

--
Al Balmer
Sun City, AZ
Apr 12 '06 #24

P: n/a
Al Balmer <al******@att.net> writes:
On Wed, 12 Apr 2006 09:12:56 +0000, Manuel Tobias Schiller
<ma**@hinterbergen.de> wrote:
Having my printer filter abort with an assert is in this case better
then silently ignoring the issue


Why are those the only two options?

Surely you could replace the assert with an orderly shutdown in a
manner less frightening (and more informative) for the user.


In a "this-can't-happen" situation, an orderly shutdown might not be
possible.

If the only sensible response to an error condition is to go back and
fix the bug in the program, an assert() is likely to be appropriate.
If the condition is something that could happen due to external
conditions, assert() is in appropriate.

--
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.
Apr 12 '06 #25

P: n/a
On Wed, 12 Apr 2006 16:28:27 GMT, Keith Thompson <ks***@mib.org>
wrote:
Al Balmer <al******@att.net> writes:
On Wed, 12 Apr 2006 09:12:56 +0000, Manuel Tobias Schiller
<ma**@hinterbergen.de> wrote:
Having my printer filter abort with an assert is in this case better
then silently ignoring the issue


Why are those the only two options?

Surely you could replace the assert with an orderly shutdown in a
manner less frightening (and more informative) for the user.


In a "this-can't-happen" situation, an orderly shutdown might not be
possible.

If the only sensible response to an error condition is to go back and
fix the bug in the program, an assert() is likely to be appropriate.
If the condition is something that could happen due to external
conditions, assert() is in appropriate.


In the given scenario, that was my point. The print filter has valid
(sic) but silly input. Nothing irreversible has happened yet. An
assert() is not appropriate.

I actually can't remember, in over 20 years of C programming, a
situation where assert() was appropriate in a production program,
although I've used the equivalent in assembler (if the hardware screws
up, halt the processor and let the failsafes handle it.)

--
Al Balmer
Sun City, AZ
Apr 12 '06 #26

P: n/a
"Manuel Tobias Schiller" <ma**@hinterbergen.de> wrote in message
news:sl*****************@ws02.hinter.bergen...
On 2006-04-11, CBFalconer <cb********@yahoo.com> wrote:
Manuel Tobias Schiller wrote:
On 2006-04-11, Kiru Sengal <ki*********@gmail.com> wrote:
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 agree that ordinary user errors (wrong parameters/incorrect usage
etc.) should be handled with a decent error message on stderr. However,
catching things that "can't" happen with assert might be a good idea; in
my case, a user had set up his spooling system so strangely that it fed
valid input to my driver, however a 100 by 100 pixel wide input for an
A4 page at 600 dpi is ridiculous (and points to wrong usage of the other
filters in the print data filtering chain), and these small dimensions
triggered an "unthought-of" bug in the code that enforced page margins.
Having my printer filter abort with an assert is in this case better
then silently ignoring the issue, because one might damage hardware
otherwise.


Ah, but if you had thought to include the assert(), you should have also
thought to include error-handling code as well. Nobody says you have to
silently ignore errors (particularly user-induced ones) in production
builds.

However, assert() is intended to protect programmers from their own
mistakes; in theory, those mistakes will all be caught during development or
testing. For catching user errors, another mechanism should be used, even
if it's just dumping a message to stderr and aborting.

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 ***
Apr 13 '06 #27

P: n/a
"Keith Thompson" <ks***@mib.org> wrote in message
news:ln************@nuthaus.mib.org...
"Stephen Sprunk" <st*****@sprunk.org> 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.


I generally write C99 and, if people need my code to work on older
compilers, I let them submit patches that account for the differences.
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
Good point.
[...]
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.


I'll leave the final decision to the C experts, but IIRC the assert macro is
only defined if one includes <assert.h>, so if you don't include that file
you're legal defining your own. Not surprisingly, people who do this tend
to include their own "assert.h" in place of <assert.h>. Probably reduces
portability, but worst case you can change the ""s to <>s for troublesome
ports.

Anyways, legal or not, it's the single most re-defined standard macro out
there, and people expect it to work even if it's frowned on by ISO.

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 ***
Apr 13 '06 #28

P: n/a
On 2006-04-12, Al Balmer <al******@att.net> wrote:
On Wed, 12 Apr 2006 16:28:27 GMT, Keith Thompson <ks***@mib.org>
wrote:
Al Balmer <al******@att.net> writes:
On Wed, 12 Apr 2006 09:12:56 +0000, Manuel Tobias Schiller
<ma**@hinterbergen.de> wrote:

Having my printer filter abort with an assert is in this case better
then silently ignoring the issue

Why are those the only two options?

Surely you could replace the assert with an orderly shutdown in a
manner less frightening (and more informative) for the user.


In a "this-can't-happen" situation, an orderly shutdown might not be
possible.

If the only sensible response to an error condition is to go back and
fix the bug in the program, an assert() is likely to be appropriate.
If the condition is something that could happen due to external
conditions, assert() is in appropriate.


In the given scenario, that was my point. The print filter has valid
(sic) but silly input. Nothing irreversible has happened yet. An
assert() is not appropriate.

I actually can't remember, in over 20 years of C programming, a
situation where assert() was appropriate in a production program,
although I've used the equivalent in assembler (if the hardware screws
up, halt the processor and let the failsafes handle it.)

You're right there, once one has recognized that an error can happen,
one should catch it and handle it appropriately (even if such handling
consists only of writing something to stderr and aborting the process),
however, I'm talking about the time before you realise that a certain
error can happen. In my case, I happened to spot this bug in my code
because it resulted in a negative number of scanlines to process (skip a
few scanlines on a page which has very few anyway, and you'll have the
nicest underflow you can imagine), and I had left that assert in the code
which triggered at once. Well, I guess that writing drivers without
documentation for the underlying hardware (the GDI printer) might
sometimes be a little different from writing ordinary applications because
asserts in production code do not neccessarily hurt in this particular
situation (remember, strictly speaking, you are never sure that you're
doing the right thing in your software...).

Anyway, I learned a lot about assert.

Thanks everyone.

Manuel

--
Homepage: http://www.hinterbergen.de/mala
OpenPGP: 0xA330353E (DSA) or 0xD87D188C (RSA)
Apr 13 '06 #29

This discussion thread is closed

Replies have been disabled for this discussion.