NDEBUG and assert macros.

P

pereges

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 ?
 
N

Nick Keighley

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
 
J

Jens Thoms Toerring

pereges said:
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
 
R

rahul

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.
 
V

vippstar

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

santosh

William said:
/* 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 = a + b;
}

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>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top