1

Would anyone here recommend using debug statements such as the following in production quality code?

I think these are personally one of the easiest to include or exclude, but they make the code hard to read so alternatives would be better

#ifdef DEBUG 
    perror("open");
    exit(1);
#endif
// Otherwise here we just skip the debug error or try to recover?

I've seen people use "debug print" macro's too, similar to these

#define TRACE(args) do { fprintf args } while (0)

// And use them like this
TRACE((stderr, "Failed to open file at path /.app/config"));

// And when debugging is disabled they change the macro to
#define TRACE(args) do {} while(0)

But the second technique seems rather messy to me, it's more flexible with variable argument lists but i prefer to use C89 so this is not a possibility.

We can also use asserts of course, but this is rather less descriptive than our own defined error messages. However i like them very much since they're super easy to enable or disable without a mess, and on top of that it prints the line / file where the error occurred.

int fd = open("testfile.c", O_RDONLY | O_NONBLOCK);
assert(fd != -1);

What is the accepted method to include debug statements in programs? Or should we just wing the whole idea and scrap debug statements in general.

I really would like to use debug statements in my program so that errors are more clear, but is it even worth it?

2

3 Answers 3

6

Conditional compilation is commonly used for debugging statement. You will therefore find these #ifdef DEBUG of NDEBUG blocks in production quality code. Because the same code that was not guaranteed as production quality just before it passed the extensive quality assurance.

Interestingly, the symbol NDEBUG was already used in the C89 standard library to define the behavior of assert (see C89, section 4.2), and you'll find many books that made such conditional compilation practice a real language idiom even if the original K&R did not use it.

Of course, the use of assert() is much more readable. But assert is very limited in terms of behavior (it's necessary an exit) and messages. Your first example for uses a precise system error message in addition to the string: An assert would not provide the same level of details.

Moreover the kind of logging that your TRACE example offers is very different from an assertion. This can help to understand a very complex and unexpected flow of control without interrupting it. But you are right about the weird style. Using a loop is confusing here, and args needs to be enclosed in a double parenthesis, which seems error prone. Instead of reinventing the wheel it would perhaps have been more effective to use a proper, proven and much more powerful logging library.

1
  • 1
    “using a loop is confusing here” – no, do { ... } while (0) is the normal idiom for writing a statement-level macro in C that must be followed by a semicolon. But yes, it's probably better to use an existing logging library rather than writing these macros by hand.
    – amon
    Sep 2, 2021 at 12:47
1

TL;DR: IMHO, debug code has no place in production code.

Debug code is, as per its name, code to help you debug your program. That level of debugging should be completed before the product is shipped.

Equally, any form of error message in production use should be sufficient to inform support, but be opaque enough that an user doesn't really know what it means - after all, a run-time failure indicates that something catastrophic has gone wrong, which implies a design flaw, a security vulnerability, or some other unhandled exception.

If your design is complete enough to identify potential failures, then include some appropriate error handling...

int fd = open("testfile.c", O_RDONLY | O_NONBLOCK);

if ( fd == -1 )
{
    /* Error handling and recovery */
}
else
{
    /* Normal operation */
}

The only exception could be, in a hosted situation, start-up validation of inputs/environment - but once the application is running, unplanned/uncommanded termination should be a no-no.

-3

You use whatever helps you finding problems in your code. You may want logging that customers can send to you to identify problems in the field. You want configurable logging on your developer machine. You want crash reports that get sent to you automatically.

1
  • Would you recommend using one of the methods above, what is the most reasonable way to do this without code clutter? I could write it to a file or something similar but then I'd still be left with the question do i use #if DEBUG // Code here #endif or something else? I want to avoid people who need to work on my code base in the future from having a hard time reading it, specially with a ton of debug statements it can get messy. And it makes maintenance also easier for myself Aug 27, 2021 at 19:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.