adding debugs in the code

S

sinbad

i often find adding debugs, ruins the readability of the code.
i've checked many projects, where in often each debug statement
spans 7 to 8 lines, which makes the code look ugly and even
incomprehensible. so here's my question, are there any techniques
that can be used to add debugs in a clean manner. i know it sound
not much like a C related question at first, but, i am looking if
c-lang has anything to offer in this regard.

thanks
 
I

Ian Collins

i often find adding debugs, ruins the readability of the code.
i've checked many projects, where in often each debug statement
spans 7 to 8 lines, which makes the code look ugly and even
incomprehensible. so here's my question, are there any techniques
that can be used to add debugs in a clean manner. i know it sound
not much like a C related question at first, but, i am looking if
c-lang has anything to offer in this regard.

Avoid them altogether and use comprehensive unit tests.
 
E

Eric Sosman

i often find adding debugs, ruins the readability of the code.
i've checked many projects, where in often each debug statement
spans 7 to 8 lines, which makes the code look ugly and even
incomprehensible. so here's my question, are there any techniques
that can be used to add debugs in a clean manner. i know it sound
not much like a C related question at first, but, i am looking if
c-lang has anything to offer in this regard.

If a piece of debugging logic must do a lot of stuff, it
will require a non-trivial amount of code. This will be true
no matter what language is used. If the debugging code is
repetitive, there may be ways to condense some of the repetition
away.

A few C features are specifically designed for debugging
and tracing: The __FILE__ and __LINE__ preprocessor macros,
the __func__ string, and of course the assert() macro.
 
J

Jorgen Grahn

i often find adding debugs, ruins the readability of the code.
i've checked many projects, where in often each debug statement
spans 7 to 8 lines, which makes the code look ugly and even
incomprehensible. so here's my question, are there any techniques
that can be used to add debugs in a clean manner. i know it sound
not much like a C related question at first, but, i am looking if
c-lang has anything to offer in this regard.

Explain what you mean by "debugs", and I'll try to answer.

/Jorgen
 
I

ImpalerCore

i often find adding debugs, ruins the readability of the code.
i've checked many projects, where in often each debug statement
spans 7 to 8 lines, which makes the code look ugly and even
incomprehensible. so here's my question, are there any techniques
that can be used to add debugs in a clean manner. i know it sound
not much like a C related question at first, but, i am looking if
c-lang has anything to offer in this regard.

One solution is to abstract the behavior of a debug or error checking
statement and use macros to perform the code generation.

For example, in many of the functions I design, I have macros that
validate the parameters in a defensive manner.

\code (inspired from GLib)
#if !defined(C_NO_CONSTRAINTS)

#define c_return_if_fail( expr )
\
do
\

{ \
if ( expr ) {}
\
else
\

{ \
gc_signal_constraint_violation( c_constraint_violation, #expr,
\
__FILE__, __LINE__, __func__ );
\
return;
\
}
\
} while (0)

#define c_return_value_if_fail( expr, val )
\
do
\

{ \
if ( expr ) {}
\
else
\

{ \
gc_signal_constraint_violation( c_constraint_violation, #expr,
\
__FILE__, __LINE__, __func__ );
\
return (val);
\
}
\
} while (0)

#else

#define c_return_if_fail( expr ) \
do \
{ \
(void)0; \
} while (0)

#define c_return_value_if_fail( expr, val ) \
do \
{ \
(void)0; \
} while (0)

#endif /* C_NO_CONSTRAINTS */

void gc_signal_constraint_violation( c_constraint_violation_type type,
const char* expr,
const char* file,
int line,
const char* func )
{
static const char* prefix[] = { "Constraint violation",
"Unexpected condition" };

if ( *func != '\0' )
{
(void)fprintf( stderr, "%s: %s, file %s, line %d, function %s\n",
prefix[type], expr, file, line, func );
}
else
{
(void)fprintf( stderr, "%s: %s, file %s, line %d\n",
prefix[type], expr, file, line );
}
fflush( stderr );
}
\endcode

With this infrastructure, it becomes more readable to integrate
parameter validation without taking up a lot of screen space.

\code
size_t c_strlncpy( char* dst, const char* src, size_t dst_size, size_t
n )
{
size_t src_length;
size_t copy_length;

c_return_value_if_fail( dst != NULL, 0 );
c_return_value_if_fail( src != NULL, 0 );

src_length = strlen( src );
if ( src_length > n ) {
src_length = n;
}

if ( dst_size == 0 ) {
return src_length;
}

copy_length = ( src_length >= dst_size ) ? dst_size - 1 :
src_length;
if ( copy_length ) {
memcpy( dst, src, copy_length );
}
dst[copy_length] = '\0';

c_unexpected( src_length >= dst_size );

return src_length;
}
\endcode

Then, if you call 'strlncpy' with a NULL 'src' or 'dst' argument,
you'll get a message saying where the developer goofed. The behavior
is defensive, the function returns a default value, and developer
errors are systematically reported. Then after the application is
developed, you can disable constraints if needed to increase
performance.

You can take it even further by splitting the different phases:
detection, report, and response, into their own function pointers (for
report and response) to provide even more complete customization of
the error handling of the program. You could change the report to add
a message to a log file, or popup a window, and the response could be
changed to 'assert' to abort on any invalid parameter, or to save the
program's current progress to a file, or contain a breakpoint to
inspect what's going on in a debugger when some interface constraint
is violated.

I use 'c_unexpected' to report cases where the semantics for the
function allow the condition, but it is typically a mistake. In the
'strlncpy' function above, it reports to the developer of a string
truncation, but takes no action.

This programming style validates that the constraints of a function's
parameter interface; it can inform or enforce that developers call the
function properly. Add unit testing to verify the behavior of the
function itself, to make sure that a function like 'c_strlncpy'
actually does what it's supposed to.

Best regards,
John D.
 
R

ralph

i often find adding debugs, ruins the readability of the code.
i've checked many projects, where in often each debug statement
spans 7 to 8 lines, which makes the code look ugly and even
incomprehensible. so here's my question, are there any techniques
that can be used to add debugs in a clean manner. i know it sound
not much like a C related question at first, but, i am looking if
c-lang has anything to offer in this regard.

I appreciate you're asking for language solutions, but should also
consider familiarizing yourself with the many external tools and
utilities that are likely available for your platform that can
facilitate "debugging" with less instrumentation in the code.

For example, in Windows you can use items such as 'DebugBreak" and
"OutputDebugString".

A 'DebugBreak' will immediately launch an outside debugger. This
allows you easily view any value, stack, memory, ... at that point
without constructing additional code.

OutputDebugString allows one to send information to an outside viewer
within a single statement.

Other tools are available to monitor the opening and closing of files,
accessing other resources, etc.

Similar tools and more are generally available wherever a C compiler
is found. <g>

-ralph
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top