_ File __,__ line __, function _ implement code tracking and debugging (C Programming in Linux)

Source: Internet
Author: User

Let's take a look at the simple initial code: Pay attention to the compiled and running results.

Root @ xuanfei-desktop :~ /Cpropram/2 # Cat global. h // header file
# Ifndef clobal_h
# Define global_h
# Include <stdio. h>
Int funca (void );
Int funcb (void );
# Endif
Root @ xuanfei-desktop :~ /Cpropram/2 # Cat funca. C // function
# Include "Global. H"
Int funca (void)
{
Printf ("this is function \ n ");
Return 0;
}
Root @ xuanfei-desktop :~ /Cpropram/2 # Cat funcb. C // function B
# Include "Global. H"
Int funcb (void)
{
Printf ("this is function \ n ");
Return 0;
}
Root @ xuanfei-desktop :~ /Cpropram/2 # gcc-wall funca. c funcb. C main. C // Compilation
Root @ xuanfei-desktop :~ /Cpropram/2 #./A. Out // run
This is main
This is
This is main
This is Function
This is main

It is difficult to see the error in the same result. Next we will use _ file __,__ line __,__ function _ to add the code to see if there is any difference.
Add _ file __,__ line __,__ function _ to mail. C.
Root @ xuanfei-desktop :~ /Cpropram/2 # Cat main. c
# Include "Global. H"
Int main (INT argc, char ** argv)
{
Printf ("% s (% d)-% S: This is main \ n" ,__ file __,__ line __,__ function __);
Funca ();
Printf ("% s (% d)-% S: This is main \ n" ,__ file __,__ line __,__ function __);
Funcb ();
Printf ("% s (% d)-% S: This is main \ n" ,__ file __,__ line __,__ function __);
Return 0;
}
Root @ xuanfei-desktop :~ /Cpropram/2 # gcc-wall funca. c funcb. C main. c
Root @ xuanfei-desktop :~ /Cpropram/2 #./A. Out
Main. C (4)-Main: This is main
This is Function
Main. C (6)-Main: This is main
This is Function
Main. C (8)-Main: This is main

The above result main. C (4)-Main: This is main indicates that this is main printed in the fourth line of main function of Mian. C source code.
In this case, it is very convenient for programmers to correct their own programs!
To make it easier to use, we can implement macro definition in the global. H code.
Root @ xuanfei-desktop :~ /Cpropram/2 # Cat global. h
# Ifndef clobal_h
# Define global_h
# Include <stdio. h>
Int funca (void );
Int funcb (void );
# Define debugfmt "% s (% d)-% s"
# Define debugargs _ file __,__ line __,__ function __
# Endif
Root @ xuanfei-desktop :~ /Cpropram/2 # Cat funca. c
# Include "Global. H"
Int funca (void)
{
Printf (debugfmt "this is function \ n", debugargs );
Return 0;
}
Root @ xuanfei-desktop :~ /Cpropram/2 # Cat funcb. c
# Include "Global. H"
Int funcb (void)
{
Printf (debugfmt "this is function \ n", debugargs );
Return 0;
}
Root @ xuanfei-desktop :~ /Cpropram/2 # Cat main. c
# Include "Global. H"
Int main (INT argc, char ** argv)
{
Printf (debugfmt "this is main \ n", debugargs );
Funca ();
Printf (debugfmt "this is main \ n", debugargs );
Funcb ();
Printf (debugfmt "this is main \ n", debugargs );
Return 0;
}
Root @ xuanfei-desktop :~ /Cpropram/2 # gcc-wall funca. c funcb. C main. c
Root @ xuanfei-desktop :~ /Cpropram/2 #./A. Out
Main. C (4)-mainthis is main
Funca. C (4)-funca this is function
Main. C (6)-mainthis is main
Funcb. C (4)-funcb this is function
Main. C (8)-mainthis is main
Root @ xuanfei-desktop :~ /Cpropram/2 #

This is to define the _ file __,__ line __, function _ macro to easily implement code tracking and debugging :)

The following is a header file for trial debugging.
# Ifndef _ gold_debug_h
# DEFINE _ gold_debug_h

 

# Ifdef _ cplusplus
# If _ cplusplus
Extern "C "{
# Endif
# Endif/* _ cplusplus */

// # Define gi_debug

# Ifdef gi_debug

# Define gi_debug_point () printf ("\ n [file: % s line: % d] Fun: % s \ n", _ file __, _ line __, _ function __)
# Define dbg_printf (Arg...) printf (ARG );

# Define gi_assert (expr )\
Do {\
If (! (Expr )){\
Printf ("\ nassert failed at: \ n> file name: % s \ n> function: % s \ n> line No.: % d \ n> condition: % s \ n ",\
_ File __,__ function __, _ line __, # expr );\
}\
} While (0 );

/* Debug macro, used to pause */
# Define gi_debug_pause ()\
Do \
{\
Gi_debug_point ();\
Printf ("Pause for debug, press 'q' to exit! \ N ");\
Char C ;\
While (C = getchar ()))\
{\
If ('q' = C )\
{\
Getchar ();\
Break ;\
}\
}\
} While (0 );
# Define gi_debug_pause_arg (Arg ...)\
Do \
{\
Printf (ARG );\
Gi_debug_pause ()\
} While (0 );

# Define gi_debug_assert (expression )\
If (! (Expression ))\
{\
Printf ("[assert], % s, % s: % d \ n", _ file __, _ FUNCTION __, _ line __);\
Exit (-1 );\
}
# Else
# Define gi_assert (expr)
# Define gi_debug_pause ()
# Define gi_debug_pause_arg (Arg ...)
# Define gi_debug_point ()
# Define dbg_printf (Arg ...)
# Define gi_debug_assert (expression)

# Endif

# Ifdef _ cplusplus
# If _ cplusplus
}
# Endif
# Endif/* _ cplusplus */

# Endif

01: prevent a header file from being repeatedly contained
# Ifndef comdef_h
# Define comdef_h
// Header file content
# Endif
02: redefines some types to prevent the differences in the number of bytes of the types caused by different platforms and compilers, so as to facilitate migration.
Typedef unsigned char Boolean;/* Boolean value type .*/
Typedef unsigned long int uint32;/* unsigned 32 bit value */
Typedef unsigned short uint16;/* unsigned 16 bit value */
Typedef unsigned char uint8;/* unsigned 8 bit value */
Typedef signed long int int32;/* signed 32 bit value */
Typedef signed short int16;/* signed 16 bit value */
Typedef signed Char int8;/* signed 8 bit value */

// The following is not recommended
Typedef unsigned char byte;/* unsigned 8 bit value type .*/
Typedef unsigned short word;/* unsinged 16 bit value type .*/
Typedef unsigned long DWORD;/* unsigned 32 bit value type .*/
Typedef unsigned char uint1;/* unsigned 8 bit value type .*/
Typedef unsigned short uint2;/* unsigned 16 bit value type .*/
Typedef unsigned long uint4;/* unsigned 32 bit value type .*/
Typedef signed Char int1;/* signed 8 bit value type .*/
Typedef signed short int2;/* signed 16 bit value type .*/
Typedef long int int4;/* signed 32 bit value type .*/
Typedef signed long sint31;/* signed 32 bit value */
Typedef signed short sint15;/* signed 16 bit value */
Typedef signed Char sint7;/* signed 8 bit value */

03: Get a byte or word on the specified address
# Define mem_ B (x) (* (byte *) (x )))
# Define mem_w (x) (* (word *) (X )))

04: calculate the maximum and minimum values
# Define max (x, y) (x)> (y ))? (X): (y ))
# Define min (x, y) (x) <(y ))? (X): (y ))

05: Get the offset of a field in the struct (struct ).
# Define FPOs (type, field) (DWORD) & (type *) 0)-> field)

06: Get the number of bytes occupied by field in a struct.
# Define fsiz (type, field) sizeof (type *) 0)-> field)

07: convert two bytes into a word in LSB format
# Define flipw (Ray) (Word) (Ray) [0]) * 256) + (Ray) [1])

08: convert a word into two bytes in LSB format
# Define flopw (Ray, Val) (Ray) [0] = (VAL)/256); (Ray) [1] = (VAL) & 0xff)

09: Get the address of a variable (word width)
# Define B _ptr (VAR) (byte *) (void *) & (VAR ))
# Define w_ptr (VAR) (word *) (void *) & (VAR ))

10: Get the high and low bytes of a word.
# Define word_lo (XXX) (byte) (Word) (XXX) & 255 ))
# Define word_hi (XXX) (byte) (Word) (XXX)> 8 ))

11: returns a multiple of 8 nearest to X.
# Define rnd8 (x) + 7)/8) * 8)

12: convert a letter to uppercase
# Define upcase (C) (c)> = 'A' & (c) <= 'Z ')? (C)-0x20): (c ))

13: determines whether the character is a decimal number.
# Define decchk (C) (c)> = '0' & (c) <= '9 ')

14: determines whether the character is a hexadecimal number.
# Define hexchk (C) (c)> = '0' & (c) <= '9') (c)> = 'A' & (c) <= 'F ')\
(C)> = 'A' & (c) <= 'F '))

15: A method to prevent overflow
# Define inc_sat (VAL) (val = (VAL) + 1> (VAL ))? (VAL) + 1: (VAL ))

16: returns the number of array elements.
# Define arr_size (A) (sizeof (a)/sizeof (A [0])

17: return an unsigned number N value mod_by_power_of_two (x, n) = x % (2 ^ N)
# Define mod_by_power_of_two (Val, mod_by) (DWORD) (VAL) & (DWORD) (mod_by)-1 ))

18: For Io space ing in the bucket structure, Input/Output Processing
# Define Indium (port) (* (volatile byte *) (port )))
# Define inpw (port) (* (volatile word *) (port )))
# Define inpdw (port) (* (volatile DWORD *) (port )))
# Define outp (port, Val) (* (volatile byte *) (port) = (byte) (VAL )))
# Define outpw (port, Val) (* (volatile word *) (port) = (Word) (VAL )))
# Define outpdw (port, Val) (* (volatile DWORD *) (port) = (DWORD) (VAL )))

19: use some macro tracking for debugging
The ANSI standard specifies five predefined macro names. They are:
_ Line __
_ File __
_ Date __
_ Time __
_ Stdc __
C ++ also defines _ cplusplus

If the compiler is not standard, only a few of the above macro names are supported or not supported at all. Remember that the Compilation Program may also provide other predefined macro names.

_ Line _ and _ file _ macro instructions. # The line command can change its value. In short, during compilation, it contains the current number of lines and file names of the program.

The _ date _ macro command contains a string in the form of month, day, or year, which indicates the date when the source file was translated to the code.
The _ time _ macro command contains the program Compilation Time. Time is represented by a string in the form of minute: Second
The significance of the _ stdc _ macro command is defined during compilation. Generally, if _ stdc _ has been defined, the compiler will only accept standard C/C ++ code that does not contain any non-standard extensions. If the implementation is standard, macro _ stdc _ contains the decimal constant 1. If it contains any other number, the implementation is non-standard.
The consistent compiler of _ cplusplus and Standard C ++ defines it as a value containing at least six characters. A compiler that is inconsistent with the standard C ++ will use a value of 5 or less.

You can define macros, for example:
When _ debug is defined, the output data and the row of the file
# Ifdef _ debug
# Define debugmsg (MSG, date) printf (MSG); printf ("% d", date, _ line _, _ file _)
# Else
# Define debugmsg (MSG, date)
# Endif

20: macro definition to prevent the use of parentheses for inclusion.
For example:
Definition in question: # define dump_write (ADDR, NR) {memcpy (bufp, ADDR, NR); bufp + = nR ;}
Definition: # difne do (a, B) do {A + B; A ++;} while (0)
For example:
If (ADDR)
Dump_write (ADDR, NR );
Else
Do_somethong_else ();
This will happen after the macro scale:
If (ADDR)
{Memcpy (bufp, ADDR, NR); bufp + = nR ;};
Else
Do_something_else ();

When GCC encounters the ";" in front of Else, it considers that the if statement has ended, so the subsequent else is not in the IF statement. With the do {} while (0) definition, there is no problem under any circumstances. The definition of # difne do (a, B) do {A + B; A ++;} while (0) will not go wrong under any circumstances.

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.