469,282 Members | 2,175 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,282 developers. It's quick & easy.

NDEBUG and assert macros.

Ok, so once I'm done debugging my code(split across multiple modules)
using the assert macro, I would want to switch off all the assert
macros ued in the program. Does this mean I have to include:

#define NDEBUG

in every .c where I used assert or defining it one file would turn off
all assert macros in every file ?
Aug 1 '08 #1
9 20627
On 1 Aug, 10:44, pereges <Brol...@gmail.comwrote:
Ok, so once I'm done debugging my code(split across multiple modules)
using the assert macro, I would want to switch off all the assert
macros ued in the program. Does this mean I have to include:

#define NDEBUG

in every .c where I used assert or defining it one file would turn off
all assert macros in every file ?
It's going to have to be in every compilation unit (c file +
includes).
Many compilers support a -D option which enables you to define a macro
on the compilers command line.

gcc -DNDEBUG fred.c -ofred

or you could it in a header file and include the header file
in every c file. Then at least next time you'd only need
to change one file.

Some pitfalls with turning off assert()s. Are you *certain*
that none of them are essential eg. input validation.
Are you sure none of them have side effects?

assert (fopen (s, siseof s, in) != NULL);

--
Nick Keighley

... it is absurd to make elaborate security checks on
debugging runs, when no trust is put in the results, and
then remove them in production runs, when an erroneous
result could be expensive or disastrous.
C. A. R. Hoare
Aug 1 '08 #2
pereges <Br*****@gmail.comwrote:
Ok, so once I'm done debugging my code(split across multiple modules)
using the assert macro, I would want to switch off all the assert
macros ued in the program. Does this mean I have to include:
#define NDEBUG
in every .c where I used assert or defining it one file would turn off
all assert macros in every file ?
Every .c file that uses assert() must see the define. You can achieve
that by putting the line in every file. On the other hand, in a pro-
ject with a lot of source files one tends to have a header file that
gets included everywhere. If you have such a header file than the
simplest thing would be to put the define in that file.

Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
Aug 1 '08 #3
On Aug 1, 2:44*pm, pereges <Brol...@gmail.comwrote:
Ok, so once I'm done debugging my code(split across multiple modules)
using the assert macro, I would want to switch off all the assert
macros ued in the program. Does this mean I have to include:

#define NDEBUG

in every .c where I used assert or defining it one file would turn off
all assert macros in every file ?
<off-topic>
If you compiler supports defining it on invocation, you can have that
on the command line itself(gcc supports doing that). The general
approach is to have a Makefile with targets defined for both the
cases(defined and not defined). Even if you are debugging a single
file, a simple Makefile won't hurt. That will save you the trouble of
typing the macro definition again on again while compiling it.
</off-topic>

The other approach, would be to have the macro defined in a header
file and include it in every file you use. Before defining NDEBUG,
make sure that your assert() is not having any side effects.

assert ((fp = fopen (FILE_NAME, "rb")) != NULL); /*this will break
you code

/* the proper way to do it
fp = fopen (FILE_NAME, "rb");
assert (fp != NULL);
>assert (fopen (s, siseof s, in) != NULL);
I assume Nick either meant fgets or passed incorrect arguments to
fopen.
Aug 1 '08 #4
In article
<26**********************************@v8g2000prm.g ooglegroups.com>, rahul
<ra*********@gmail.comwrote:
...
assert ((fp = fopen (FILE_NAME, "rb")) != NULL); /*this will break
you code */

/* the proper way to do it */
fp = fopen (FILE_NAME, "rb");
assert (fp != NULL);
BAD example, since failure to open a file is ALWAYS a possibility, no
matter how well-debugged a program is. Assert is NOT for input validation,
only validation of data from other parts of the program.
Aug 1 '08 #5
On 1 Aug, 10:44, pereges <Brol...@gmail.comwrote:
Ok, so once I'm done debugging my code(split across multiple modules)
using the assert macro, I would want to switch off all the assert
macros ued in the program. Does this mean I have to include:

#define NDEBUG

in every .c where I used assert or defining it one file would turn off
all assert macros in every file ?
Actually, you need to ensure that NDEBUG is defined at the
point assert.h is included. So, if you write:

#include <assert.h>
#define NDEBUG

then assertions will still be enabled. It is generally (IMO)
a bad idea to define NDEBUG in the source itself. Instead,
define NDEBUG when you invoke your compiler. For example,
any of the following work in many environments:

$ $CC -DNDEBUG ... # Here, $CC is the path to your compiler
$ make CPPFLAGS=-DNDEBUG
$ ./configure CPPFLAGS=-DNDEBUG && make

Aug 2 '08 #6
On 1 Aug, 10:57, Nick Keighley <nick_keighley_nos...@hotmail.com>
wrote:
>On 1 Aug, 10:44, pereges <Brol...@gmail.comwrote:
>Ok, so once I'm done debugging my code(split across multiple modules)
using the assert macro, I would want to switch off all the assert
macros ued in the program.
<snip>
Some pitfalls with turning off assert()s. Are you *certain*
that none of them are essential eg. input validation.
Are you sure none of them have side effects?
If a program is using assert to validate input,
then it is abusing/misusing assert. If an assertion
has a side effect, it is a bug, for example:
assert( x = 0 ); /* oops, should be x == 0 */

In other words, if you can't turn off assertions and
still pass the test suite, the solution is to fix
the bug--it is *not* to avoid turning off the assertions.
The point relevant to the OP is that you are NOT
done debugging until you've turned off the assertions
and verified that the code still works.
Aug 2 '08 #7
On 1 Aug, 12:31, rahul <rahulsin...@gmail.comwrote:

/* the proper way to do it
fp = fopen (FILE_NAME, "rb");
assert (fp != NULL);
No. Absolutely NOT. This is utterly broken, wrong, and
heinous. This is NOT what assert is for. At all. Arghh.
If you want, you might do:

fp = Fopen( ... );
assert( fp != NULL );

This would serve as documentation to the maintainer that
the Fopen call will never return a NULL pointer. Or you
can do things like:

for( i = 0; i < N; i++) {
...
}
assert( i == N);

This documents to the maintainer that the loop
is constructed such that it will always terminate with i
hitting the upper bound. The purpose of assert is to
validate that something you believe must be true is
in fact true. Often as pre-conditions in a function call:

void add( const int *a, const int *b, int *c, size_t N )
{
size_t i;
assert( a != NULL );
assert( b != NULL );
assert( c != NULL );

for( i = 0; i < N; i++ )
c[i] = a[i] + b[i];
}

This is far safer than simply adding a comment that states
that none of the arguments can be a null pointer, since it
aborts when the unwary programmer attempts to pass a null
pointer. It is NOT doing validation. If you want to write
a function that validates, you can't use assert. For example:

int add( int *a, int *b, int *c)
{
int status = 0;
int A,B;

A = ( a == NULL ) ? 0 : *a;
B = ( b == NULL ) ? 0 : *b;
if( c == NULL )
status = -1
else
*c = A + B;
return status;
}

Here, there are some questions. For example, perhaps you want
this function to never overflow. So perhaps you might want to
ensure that it is never called with *a or *b larger than INT_MAX/2.
In that case, look through your code; if you believe that
condition is true, then make it an assertion.

assert is NOT for data validation, or to check a function call.
It is used to validate your logic and the implementation. It
should be thought of as documentation. You are telling both
the compiler and the maintainer that you believe something
will be true. If it is not, the compiler will tell you that
you are wrong by causing a run-time abort. Anytime you look at
a piece of code and think something like, "okay, right here,
either i is positive or j is odd", then write it out:
assert( i 0 || j % 2 );
This is much better than a comment for two reasons ( at least ):
1) It removes the ambiguity about the word "positive" (does it
include zero or not?)
2) It is validated by the compiler.
Aug 2 '08 #8
On Aug 2, 12:54 pm, William Pursell <bill.purs...@gmail.comwrote:
On 1 Aug, 12:31, rahul <rahulsin...@gmail.comwrote:
/* the proper way to do it
fp = fopen (FILE_NAME, "rb");
assert (fp != NULL);

No. Absolutely NOT. This is utterly broken, wrong, and
heinous. This is NOT what assert is for. At all. Arghh.
It might not be what assert is for, but it's not broken or wrong. (if
you don't mind the missing */)

<snip>
Aug 2 '08 #9
William Pursell wrote:
On 1 Aug, 12:31, rahul <rahulsin...@gmail.comwrote:

>/* the proper way to do it
fp = fopen (FILE_NAME, "rb");
assert (fp != NULL);

No. Absolutely NOT. This is utterly broken, wrong, and
heinous. This is NOT what assert is for. At all. Arghh.
If you want, you might do:

fp = Fopen( ... );
assert( fp != NULL );

This would serve as documentation to the maintainer that
the Fopen call will never return a NULL pointer. Or you
can do things like:

for( i = 0; i < N; i++) {
...
}
assert( i == N);

This documents to the maintainer that the loop
is constructed such that it will always terminate with i
hitting the upper bound. The purpose of assert is to
validate that something you believe must be true is
in fact true. Often as pre-conditions in a function call:

void add( const int *a, const int *b, int *c, size_t N )
{
size_t i;
assert( a != NULL );
assert( b != NULL );
assert( c != NULL );

for( i = 0; i < N; i++ )
c[i] = a[i] + b[i];
}

This is far safer than simply adding a comment that states
that none of the arguments can be a null pointer, since it
aborts when the unwary programmer attempts to pass a null
pointer. It is NOT doing validation. If you want to write
a function that validates, you can't use assert. For example:

int add( int *a, int *b, int *c)
{
int status = 0;
int A,B;

A = ( a == NULL ) ? 0 : *a;
B = ( b == NULL ) ? 0 : *b;
if( c == NULL )
But is it any more correct call this add with null pointer values
for 'a', 'b', or 'c' than a similar call of the previous add? Why would
one want to write a zero to *c when the function is called with clearly
invalid arguments. I personally would return the error value for all
these cases, not just when c is NULL.

I can't really decide whether using assert on function parameters is
appropriate or not. An error code, as in this code, might be silently
misused by the caller, but OTOH, it somehow seems better to *inform*
the caller of an erroneous call (thus giving it a chance to retry,
though how much real life code is this comprehensive?), than terminate
the program single-handedly. But then would checking parameters with
assert be more justified for a function that has no defined error
return codes?

IMHO assert seems much more appropriate when used to verify the
correctness of program state at various points than when it's used for
things like function parameter checking, return value checking etc.
status = -1
else
*c = A + B;
return status;
}

Here, there are some questions. For example, perhaps you want
this function to never overflow. So perhaps you might want to
ensure that it is never called with *a or *b larger than INT_MAX/2.
In that case, look through your code; if you believe that
condition is true, then make it an assertion.
In the calling code? If so I agree.

<snip>

Aug 2 '08 #10

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

4 posts views Thread by Dave | last post: by
6 posts views Thread by Alexander Malkis | last post: by
13 posts views Thread by Matthias Kaeppler | last post: by
11 posts views Thread by BigMan | last post: by
3 posts views Thread by Tony Johansson | last post: by
21 posts views Thread by Giuseppe | last post: by
27 posts views Thread by Daniel Vallstrom | last post: by
47 posts views Thread by Rob Thorpe | last post: by
13 posts views Thread by priyanka | last post: by
reply views Thread by suresh191 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.