Some methods of output debugging information in C language __c language

Source: Internet
Author: User

When debugging a program, outputting debugging information is a universal and effective method. The output debugging information generally has the following five kinds of methods:

Method One: Directly using the screen printing function printf.

This method uses the function printf to output the corresponding debugging information directly in the place where the debugging information needs to be output, and the values of some key variables.  We look at the process of debugging the method through the following fact function. #include <stdio.h>
int fact (int n)
{
int i,f=1;
for (I=1; i<=n; i++)
{
f = i;
}
return F;
}
int main ()
{
printf ("4!=%d/n", Fact (4));
return 0;
}
Program 1: A bug-seeking class function

The results of the program 1 compilation run are as follows: 4!=11

The result is an error. In order to find out the cause of the error, we are in the statement "F + i;" After that, the Insert function printf output debugging information, such as Program 2.   #include <stdio.h>
 int fact (int n)
 {
          int i,f=1;
         for (i=1 i<=n; i++)
          {
                  f = i;
                 printf ("i= %d; f=%d/n ", I, f);
        }
         return F;
 }
 int Main ()
 {
         printf ("4!=%d/n", Fact (4));
         return 0;
 }
  Program 2: Add function printf output debugging information hierarchy function

Recompile to run the program, the screen output is as follows: I=1; f=2 i=2; f=4 i=3; f=7 i=4; f=11 4!=11

The

Original statement "F = i" is wrong, should be "f *=i". Modify it Over (see program 3), and then compile the operation, the results are as follows: I=1; F=1 i=2; f=2 i=3; F=6 i=4; f=24 4!=24   #include <stdio.h>
 int fact (int n)
 {
          int i,f=1;
         for (i=1 i<=n; i++)
          {
                  f *= i;
                 printf ("i= %d; f=%d/n ", I, f);
        }
         return F;
 }
 int Main ()
 {
         printf ("4!=%d/n", Fact (4));
         return 0;
 }
  Program 3: Modifying the correct hierarchy function

Debug complete, bug found, and correct. Then you delete or comment out the function that you are adding to debug.

The disadvantage of this method is (1) in the formal release of the program need to remove or comment out these debugging statements, (2) if the program and the bug, then need to reinsert the function printf output debugging information, resulting in duplication of work.

Method Two: Customize Debug function Debug.

To avoid the disadvantage of method one, you can use conditional compilation techniques, such as program 4 to customize Debug function Debug. When the program is officially released at compile time to cancel the macro definition __debug__, debug information is not output in the officially published program. If there is a bug again, you can restore the original debug information output by simply __debug__ the macro when compiling the program. You can write a program with the purpose of inserting some debugging statements beforehand, which will benefit the debugger.  In addition, you can write a function debug as needed to output debugging information to a location other than the screen, such as a file or a syslog server. #include <stdio.h>

#ifdef __debug__
#include <stdarg.h>
void Debug (const char *FMT, ...)
{
Va_list ap;
Va_start (AP, FMT);
VPRINTF (FMT, AP);
Va_end (AP);
}
#else
void Debug (const char *FMT, ...)
{
}
#endif

int fact (int n)
{
int I, F = 1;
for (I=1; i<=n; i++)
{
f *= i;
Debug ("i=%d; f=%d/n ", I, f);
}
return F;
}
int main ()
{
printf ("4!=%d/n", Fact (4));
return 0;
}
Program 4: Custom Debug Function Debug

The disadvantage of this method is (1) debugging information is either full or not output, (2) You need to recompile the program when you want to output the debug information again.

Method Three: Debug a custom debug function with a level of debugging.

You can continue to improve the method to avoid the shortcomings of method two. We can divide the debugging information into different levels according to the detail level of the debugging information. The level of debugging information must be greater than 0, and the higher the level of debugging information, the higher the rank. In the output debugging information, if the debug level is higher than the debug information level to output debugging information, otherwise ignore the debugging information, such as program 5.  When the debug level is 0 o'clock, no debugging information is output. #include <stdio.h>
#include <stdlib.h>/* ATOI () * *

#include <stdarg.h>

int debug_level;
void debug (int level, const char *FMT, ...)
{
if (Level <= debug_level)
{
Va_list ap;
Va_start (AP, FMT);
VPRINTF (FMT, AP);
Va_end (AP);
}
}

int fact (int n)
{
int I, F = 1;
for (I=1; i<=n; i++)
{
f *= i;
Debug (i=%d, ""; f=%d/n ", I, f);
}
return F;
}
int main (int argc, char *argv[])
{
if (ARGC < 2)
{
Debug_level = 0;
}
Else
{
Debug_level = Atoi (argv[1]);
}
printf ("4!=%d/n", Fact (4));
return 0;
}
Program 5: Custom debug function with Debug level debug

Use the command "Gcc-wall-o fact fact.c" to compile program 5 to get the executable file fact. If you need to output debugging information, simply specify a debug level of not less than 250, such as running the command "./fact 250", otherwise it will not output debugging information.

It would also be harmless to include debugging information in a formal release, because you would only configure debug levels to 0 and no debugging information would appear.

The disadvantage of this approach is that it is inefficient, because a function call occurs regardless of whether the debug information requires output. If you do not need to output debugging information, this function call is redundant.

Method Four: The judgment of the debug level is placed outside of the custom debug function Debug.

To reduce unnecessary function calls, you can use a macro definition to place the judgment of debug levels outside of the function debug, such as program 6. #include <stdio.h>
#include <stdlib.h>/* ATOI () * *

#include <stdarg.h>

int debug_level;

#define DEBUG (level, FMT, arg ...)/
if (level <= debug_level) __debug (FMT, # #arg)

void __debug (const char *FMT, ...)
{
Va_list ap;
Va_start (AP, FMT);
VPRINTF (FMT, AP);
Va_end (AP);
}

int fact (int n)

{
int I, F = 1;
for (I=1; i<=n; i++)
{
f *= i;
Debug (i=%d, ""; f=%d/n ", I, f);
}
return F;
}
int main (int argc, char *argv[])
{
if (ARGC < 2)
{
Debug_level = 0;
}
Else
{
Debug_level = Atoi (argv[1]);
}
printf ("4!=%d/n", Fact (4));
return 0;
}
Program 6: The judgment of the debug level is placed outside of the custom debug function debug

This approach is only a two-integer size estimate for high level debugging information operations that do not require output. In the formal process of operation, the efficiency is improved.

But this method of debugging information output is still not perfect. For a large project, there are typically several modules, and bugs will be positioned to one or several modules. If the whole project of debugging information output, the amount will be very large, but also easy to interfere with the debugging staff's thinking. At this point, we need to output only those modules we care about debugging information, but this method does not meet our requirements. It can only according to debug level output information, for the same level of debugging information either full output, or all do not output.

Method Five: According to different functional modules to define different levels of debugging.

In Squid[1], the following function modules are defined as debug level variables and DEBUG functions: int debuglevels[max_debug_sections];
#define DEBUG (section, level)/
((_db_level = (level)) > Debuglevels[section])? (void) 0: _db_print

It is then used in the program as follows: Debug (3) ("Fwdstatefree:%p/n", fwdstate);

The above debugging function is very flexible, can be defined in different modules have different levels of debugging, when you need to debug a function, only the debug level of the module defined as the appropriate level, you can output the required debugging information.

Based on the idea of method five, I wrote my_debug.h (see procedure 7) and MY_DEBUG.C file (see procedure 8). This file can be applied in C language program, which supports different debugging levels according to different functional modules.

#ifndef My_debug_h
#define My_debug_h

#include <stdio.h>

module function number
enum {
My_section_fact = 0,
MY_SECTION_NNN1,
MY_SECTION_NNN2,
MY_SECTION_NNNN,
My_section_end,
};

External variable declaration for non-my_debug.c file
#ifndef My_debug_c
extern int __my_allow_debug_levels[my_section_end];
#endif

(internal use) to determine whether the "section" module function number allows the "Debug_level" level of debug information output
#define __MY_UNALLOW_DEBUG (section, Debug_level)/
(Debug_level > __my_allow_debug_levels[section])

Debug information output function (internal use)
#define __MY_DEBUG (FORMAT, ARG ...)/
printf ("%s:%d%s:" FORMAT, __file__, __line__, __function__, # #ARG)

Initialize the debug level for the Section module feature number
#define MY_INIT_DEBUG_LEVELS (section, Allow_debug_level)/
(__my_allow_debug_levels[section] = allow_debug_level)

Debug information output function, which is the "section" Module function number "Debug_level" level of debugging information
#define MY_DEBUG (section, Debug_level)/
(__my_unallow_debug (section, debug_level))? (void) 0: __my_debug

#endif//my_debug_h
Program 7:my_debug.h

#define My_debug_c
#include "My_debug.h"

int __my_allow_debug_levels[my_section_end];

Program 8:MY_DEBUG.C

To use the above file, you must extend the module function number enumeration type in my_debug.h based on the number of functional modules, and then invoke the macro definition My_init_debug_levels the debug level of the corresponding module in the appropriate location of the program. Write the following locations where you want to output debug information. My_debug (My_section_fact,) ("i=%d; f=%d/n ", I, f);

Let's look at how to use them in fact.c (see Program 9). #include <stdio.h>
#include <stdlib.h>

#include "My_debug.h"

int fact (int n)
{
int I, F = 1;
for (I=1; i<=n; i++)
{
f *= i;
My_debug (My_section_fact,) ("i=%d; f=%d/n ", I, f);
}
return F;
}
int main (int argc, char *argv[])
{
if (ARGC < 2)
{
My_init_debug_levels (my_section_fact, 0);
}
Else
{
My_init_debug_levels (My_section_fact, Atoi (argv[1));
}
printf ("4!=%d/n", Fact (4));
return 0;
}
Program 9:FACT.C

Reference documents:

[1] squid, http://www.squid-cache.org

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.