Basic Debugging Technology for C/C ++ in Linux: a preliminary understanding

Source: Internet
Author: User

 

Author: gnuhpc
Website: blog.csdn.net/gnuhpc

1. Several principles of debugging technology

Surprise principle: finding a mistake is a pleasant surprise. Do not be afraid of it, but be grateful.
Starting from scratch: the use of tests starts from scratch and does not involve boundary data for the moment. Although this may obscure some bugs, it may be able to find the most important bugs, for example, your program contains a huge loop body, and the bug that is most easily discovered is executed in the first or second loop.
Top-down rule: Select step over rather than step into to save time.
Segmentation fault principle: When a segment error occurs, the first thought should not be printf but debugger, because in the debugger, You can see which line of your code causes an error, more importantly, you can get more useful information through tools such as backtrace.
Half-fold search criteria: when looking for bugs, you can make full use of the editor and other tools for half-fold search. For details, see the following examples.
2. Code debugging tools in Linux

The main use of GDB, as well as GDB-based graphical tools, such as DDD or eclipse, depends on your personal habits.

Command-line GDB can be started quickly and can be used in an SSH terminal. The operations are simple and will not crash when debugging GUI programs, however, compared with graphics, it is inconvenient to debug or set breakpoints in a single step.

Of course, you can use vim and other editor plug-ins or patches (clewn or vimgdb) to make up for this defect, in gdb6.1 or later versions, you can use the GDB-tui mode (or press Ctrl-X-A in the command line mode of GDB) to open a text interface mode similar to the graphic interface, in this interface you can use the up and down keys to view the source code (CTRL-P and CTRL-N to view the entered command ).

Alternatively, you can use the cgdb tool (fortunately, this project was stopped for three years and someone started to maintain it again), which wraps GDB with curses, provides some useful feature (switch the ESC and I keys between the code and command boxes; Support vim-type operations in the code box; Support the tab key completion command in the Command box; when you move the row to which you want to add a breakpoint (the row number is highlighted in white), use the space key. After the settings, the row number turns red ;). In addition, eclipse is recommended when debugging C-S programs.

In this article, we will focus on the operations of DDD, because this tool combines the operations of GDB command lines and graphical interfaces. For more information, see the manual of each tool.

3. GDB command line basic operations

Set breakpoint: B linenumber
Run the program: R args1 args2...
Terminate the program permanently: Kill
One-step execution: n (tips1: you can press enter to repeat the previous operation. This feature is useful for single-step debugging ).
Single Step-in: S
Continue execution: c
Set a temporary breakpoint: Tb linenumber can be understood as a one-time breakpoint. Unlike a breakpoint, a temporary breakpoint only takes effect during the first execution.
View variable: P
Set observation points:
W expression: When expression is a variable name, the variable will stop executing when it changes. You can also use conditions, such as W (z> 28). When Z is greater than 28, the program stops. Note that the observation points generally use variables in a larger range, rather than local variables, because the observation points set on the local variables are at the local end (for example, when the function of the variable is executed) it is canceled.
Of course, this does not include the case of main, because the program ends after the main function is executed.
View stack frames:
Stack frame refers to the place where the running information of a function call (including local variables, parameters, and the location where the function is called) is stored during a function call. Every time a function is called, a new frame is pushed into a frame maintained by the system. At the top of the stack, information about the currently running function is displayed, when the function call ends, it is displayed and analyzed.
In GDB, frame 0 is the current frame, frame 1 is the parent frame of the current frame, and frame 2 is the parent frame of the parent frame. The down command is reverse. This is a very useful information, because the information in some early frames may give you some tips.
Backtrace to view the entire frame Stack
Note: back and forth in the frame does not affect program execution.
Example: insert Sorting Algorithm debugging

Use pseudocode to describe the process as follows:

 

The code to be debugged is as follows:

//

// Insertion sort,

//

// Usage: insert_sort num1 num2 num3..., where the numi are the numbers

// Be sorted

Int X [10], // input Array

Y [10], // workspace Array

Num_inputs, // length of input Array

Num_y = 0; // current number of elements in Y

Void get_args (int ac, char ** AV)

{Int I;

Num_inputs = ac-1;

For (I = 0; I <num_inputs; I ++)

X [I] = atoi (av [I + 1]);

}

Void scoot_over (int jj)

{Int K;

For (k = num_y-1; k> JJ; k ++)

Y [k] = Y [k-1];

}

Void insert (INT new_y)

{Int J;

If (num_y = 0) {// y empty so far, easy case

Y [0] = new_y;

Return;

}

// Need to insert just before the first y

// Element that new_y is less

For (j = 0; j <num_y; j ++ ){

If (new_y <Y [J]) {

// Shift y [J], Y [J + 1],... rightward

// Before inserting new_y

Scoot_over (j );

Y [J] = new_y;

Return;

}

}

}

Void process_data ()

{

For (num_y = 0; num_y <num_inputs; num_y ++)

// Insert new Y in the proper place

// Among y [0],..., Y [num_y-1]

Insert (X [num_y]);

}

Void print_results ()

{Int I;

For (I = 0; I <num_inputs; I ++)

Printf ("% d \ n", Y [I]);

}

Int main (INT argc, char ** argv)

{Get_args (argc, argv );

Process_data ();

Print_results ();

}
Let's compile:

Gcc-g-wall-O insert_sort ins. c

Note that we should use the-G option to tell the compiler to save the symbol table in the executable file-the memory address corresponding to the variables and code in our program.

Now let's start running. We use the "starting from scratch" principle. First, we use two numbers for testing:

./Insert_sort 12 5

We found that the program did not exit, and it seems to have entered an endless loop. We started to use DDD to debug this program:

Ddd insert_sort

Run the program and input two parameters:

R 12 5

At this time, the program continues running and does not exit. Press Ctrl + C to pause the program execution.

(GDB) R 12 5
^ C
Program received signal SIGINT, interrupt.
0x080484ff in insert (new_y = 3) at insert_sort.c: 45
/Home/gnuhpc/mycode/debug/chapter_01/insert_sort/pg_019/insert_sort.c: 45: 939: Beg: 0x80484ff
(GDB)

 

We can see that the program stops at 49th rows. Let's take a look at the current num_y value:

(GDB) P num_y
$1 = 1

$1 indicates the first variable you want GDB to tell you. After finding this place, let's see what happened at num_y = 1. We have the insert function (row 27th) set the breakpoint (you can also directly use break insert to set the breakpoint at the entry of this function), and set GDB at the breakpoint 1 (you can view the breakpoint through the info break command) only when num_y = 1:

(GDB) B 27
Breakpoint 1 at 0x80484a1: file insert_sort.c, line 27.
(GDB) condition 1 num_y = 1
(GDB)

The preceding command can also use break if to combine:

(GDB) Break 27 if num_y = 1

Then run the program, and then use n single-step debugging to find that we jumped to the exit of the function:

 

Now let's look at the value of num_y to check whether the for loop is executed.

(GDB) P num_y
$2 = 0

In this case, num_y is 1 when we enter this function, but now num_y is 0, and this variable is changed in the middle. Now you know the bug is within 30-36 lines. At the same time, you can find that lines 31-33 have been skipped through single-step debugging. Lines 34 and 35 have behavior comments, so the bug is in lines 30th or 36th.

Now let's take a closer look at the two rows and draw a conclusion: There is a typical if condition written as a value assignment error in the 30 rows. The fatal thing is that this variable is a global variable, this directly causes 49 rows of for loop variables to be reset all the time. Modify and re-compile (you can open another editor without exiting DDD), and then run

(GDB) R 12 5
5
0

Although there is no endless loop, the results are still incorrect.

Note that array y is empty at the beginning. In the first loop of #49, the value of Y [0] should be 12. In the second loop, the program should move 12 to 5 to make room for insertion, but at this time the result looks like 5 has replaced 12.

In this case, the single-step debugging enters the for loop. #37 check that the value of Y [0] is indeed 12. When we run the scoot_over function, we skip this step and continue to #41 Based on the top-down principle. Check whether the result is correct and then decide whether to step into the scoot_over function:

 

We found that 12 was not moved at all, which indicates that the scoot_over function is faulty. we removed the breakpoint of the insert function entry and set the breakpoint at the scoot_over entry. When num_y = 1, it ended: B scoot_over if num_y = 1. After further single-step debugging, the #23 for loop is not executed.

(GDB) P jj
$12 = 0
(GDB) P K
$13 = 0

We can see that the for loop condition is not met and the loop cannot be entered. Here 12 should be moved from Y [0] to Y [1], so we are sure it is a loop initialization error. It should be K = num_y. modify this part and compile and run it, the program has a segment error. We clear all the breakpoints and then

(GDB) r

Program received signal SIGSEGV, segmentation fault.
0x08048483 in scoot_over (JJ = 0) at insert_sort.c: 24
(GDB)

It is pointed out that seg fault appears in 24 rows, then either K exceeds the array boundary, or the k-1 is negative. Print the value of K and we will find:

(GDB) P K
$14 = 992
(GDB)

It is much larger than K's value. If the value of num_y is 1, it indicates that an error occurred while processing the second number to be sorted, and then the JJ value is printed. If the value is 0, it is found that our for loop K ++ should be changed to K -.

Compile and run. OK is found. However, an error occurs when multiple data entries are run:

(GDB) R 12 5 19 22 6 1
1
5
6
12
0
0

Program exited with Code 06.
(GDB)

We can see that there is a problem in sorting from 19 in the result. We set a breakpoint in the row for (j = 0; j <num_y; j ++, when the condition is new_y = 19:

(GDB) Break 36 if new_y = 19
Breakpoint 10 at 0x80484b1: file insert_sort.c, Line 36.
(GDB)

After one-step debugging, we found that we did not process when the element to be inserted is greater than all elements. After #44, add y [num_y] = new_y; Re-compile and run the program correctly. Now, we use a simple example to demonstrate how to use GDB for debugging.

References:
Art of debugging
Linux debugging and Performance Tuning: Tips and Techniques

Author: gnuhpc
Website: blog.csdn.net/gnuhpc

 

This article from the csdn blog, reproduced please indicate the source: http://blog.csdn.net/gnuhpc/archive/2010/12/03/6051867.aspx

 

Related Article

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.