debug msgs

K

Khookie

Hi everyone

The program I'm writing is getting bigger, hence not as easy to debug.

So I have this on one of my core header files, which I include in just
about every .c file, and I use it everywhere to print out diagnostic
msgs.

#ifdef NDEBUG
#define debug(x) ((void)0)
#else /* debugging enabled */
#define debug(e) fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__,
e)
#endif

Hope it makes sense... the thing is, is there functionality like
selectively putting out diagnostic msgs already somewhere in standard
C? Or is this a case of roll your own?

Chris
 
M

Malcolm McLean

Khookie said:
Hi everyone

The program I'm writing is getting bigger, hence not as easy to debug.

So I have this on one of my core header files, which I include in just
about every .c file, and I use it everywhere to print out diagnostic
msgs.

#ifdef NDEBUG
#define debug(x) ((void)0)
#else /* debugging enabled */
#define debug(e) fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__,
e)
#endif

Hope it makes sense... the thing is, is there functionality like
selectively putting out diagnostic msgs already somewhere in standard
C? Or is this a case of roll your own?
Use assert() to indicate that caller has made an error - eg called a square
root routine with a negative number, or a string function with a null.
However not for user input errors.

assert() can compile to nothing in a release build. A correct program should
never trigger an assert().

Otherwise you have to mess about with debug flags and definitions, as you
are doing. You tend to find that this breaks down as programs become more
complex and programmers start demanding different debug levels.
 
F

Flash Gordon

Malcolm McLean wrote, On 29/12/07 16:09:
Use assert() to indicate that caller has made an error - eg called a
square root routine with a negative number, or a string function with a
null.
However not for user input errors.

Good advice.
assert() can compile to nothing in a release build. A correct program
should never trigger an assert().

True, but bugs happen.

Actually, for some applications it is better to leave these traps in
because a program abort with a message is better than producing an
incorrect result. As with everything else, you have to consider your own
specific requirements.
Otherwise you have to mess about with debug flags and definitions, as
you are doing. You tend to find that this breaks down as programs become
more complex and programmers start demanding different debug levels.

At which point you introduce a more sophisticated system. Personally I
am using one where the prototype is something like (from memory):
dbg(char *facility, char *format, ...);

We then provide a runtime mechanism to enable debug specific facilities
or on everything.
 
A

Army1987

Khookie said:
Hi everyone

The program I'm writing is getting bigger, hence not as easy to debug.

So I have this on one of my core header files, which I include in just
about every .c file, and I use it everywhere to print out diagnostic
msgs.

#ifdef NDEBUG
#define debug(x) ((void)0)
#else /* debugging enabled */
#define debug(e) fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__,
e)
Note that %d is for int, but __LINE__ is only guaranteed to be an integer
constant. I'd use %lu and cast __LINE__ to unsigned long, just in case you
should use it on line 32769 on a 16-bit system...
#endif

Hope it makes sense... the thing is, is there functionality like
selectively putting out diagnostic msgs already somewhere in standard C?
Or is this a case of roll your own?
There is assert(), but it terminates the program on failure. Look it up.
 
S

SM Ryan

# > assert() can compile to nothing in a release build. A correct program
# > should never trigger an assert().
#
# True, but bugs happen.

Better to leave a production code at a distant customer site run
incorrectly producing detectably bad answers without detecting them
or warning the customer. If customers receive error messages,
however cryptic you make them, they are too ready to demand answers
and a fix. If you can delude them into believing the problem is
somewhere other than what you sold them, you evade blame when their
business fails.

Think in terms annoying dashboard lights. Wouldn't you rather just drive
until the engine seizes up or explodes rather than those blinking idiot
lights that you never understand?
 
R

Richard Heathfield

SM Ryan said:
# > assert() can compile to nothing in a release build. A correct program
# > should never trigger an assert().
#
# True, but bugs happen.

Better to leave a production code at a distant customer site run
incorrectly producing detectably bad answers without detecting them
or warning the customer.

Better not to let the code ship with code that can fail assertions.

Think in terms annoying dashboard lights. Wouldn't you rather just drive
until the engine seizes up or explodes rather than those blinking idiot
lights that you never understand?

Think in terms of scaffolding on a building site. If the building can't
stand up without the scaffolding, it isn't ready for people to move in
yet.
 
P

Peter Nilsson

Army1987 said:
Note that %d is for int, but __LINE__ is only guaranteed to
be an integer constant.

And it needn't be decimal or unsuffixed. Indeed, it may expand
to __line or some other 'magic' implementation macro.

Also note that __LINE__ is only a guide. It's the 'presumed'
line number, which apparently gives some latitude, if gcc 4.2
is any guide...

% type line.c
#include <stdio.h>

#define DUMP_LINE() printf("%d\n", (int) __LINE__); \
printf("%d\n", (int) __LINE__)

int main(void)
{
DUMP_LINE(); \
DUMP_LINE();

return 0;
}

% acc line.c -o line.exe

% line
8
8
9
9

I would have expected four 8s since both line splices should
happen in the same translation phase, prior to macro evaluation.
I'd use %lu and cast __LINE__ to
unsigned long, just in case you should use it on line 32769
on a 16-bit system...

I prefer to keep source files less than 32768 lines and cast
__LINE__ to int.
 
R

Richard Heathfield

Peter Nilsson said:
And it needn't be decimal or unsuffixed.

Your comments on __LINE__ are certainly valid, but they apply only to C99,
which hardly anyone actually uses. The C89 Standard says that __LINE__ is
a decimal constant, which means that it consists entirely of decimal
digits:

decimal-constant:
nonzero-digit
decimal-constant digit

No suffix is allowed.
Indeed, it may expand
to __line or some other 'magic' implementation macro.

I see no licence allowing this behaviour (other than the "as if" rule).
Also note that __LINE__ is only a guide.

Again, this is C99-specific. In C89, it is defined as "The line number of
the current source line (a decimal constant)."
 
M

Malcolm McLean

Richard Heathfield said:
SM Ryan said:


Better not to let the code ship with code that can fail assertions.



Think in terms of scaffolding on a building site. If the building can't
stand up without the scaffolding, it isn't ready for people to move in
yet.
You don't always have a choice.
Guaranteeing bug-free software might imply extremely long development times
and highly paid programmers.
Obviously if the software will kill people if it fails,then you would demand
this, but still only up to a point - generally engineers say that it is
worth spending about 2 million pounds to save an unknown victim's life. If
you know the identity of the person who will be killed it's a different and
much more thorny problem, but fortunately that doesn't crop up too often.

However if the software is being used to dispatch goods from a warehouse,
yes it is thundering nuisance if Mr Fryer the chippie gets a bag of diced
potatoes rather than sliced potatoes. But all it means is that someone has
to drive over in a minivan to correct the order. Total cost to the customer,
maybe 50 quid. If the system is saving them two clerk's salaries of 20,000
pounds a year each, it doesn't make much sense to delay deployment until
every teething problem is out.
 

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

Members online

Forum statistics

Threads
473,995
Messages
2,570,228
Members
46,818
Latest member
SapanaCarpetStudio

Latest Threads

Top