LinuxQuestions.org
Help answer threads with 0 replies.
Go Back   LinuxQuestions.org > Linux Answers > Programming
User Name
Password

Notices


By edbarx at 2014-05-18 04:38
This howto is intended for anyone who never succeeded to use gdb successfully.
gdb, being a CLI application, may not appeal to the eye, but my experience in using it, has proven that it is a very good debugger.

Step 1:
Compile your source code using the g++/gcc -g option. This tells the compiler to include debugging information in the compiled executable.

Step2:
While at the directory containing the freshly compiled executable, invoke gdb as follows:
Code:
gdb executable-name
Step 3:
Set breakpoints as follows:
For the main source file, ie where main() is implemented, use:
Code:
b 51
The 51 is the line number where the breakpoint is placed. In your case, it will be a different line number.

For other files, say parser.cpp, use:
Code:
b parser.cpp:125
Your project will most likely have differently named files. parser.cpp should be accompanied by a parser.h file: I don't know whether opting to only use .cpp files works.

Step 4:
Run the program by typing 'r' and by pressing Enter.

The actual debugging.
  1. To step over a line of code use: 'n'.
    Stepping a line a code forces the debugger to fully execute that line of code. That means, if there is a function call, say:
    Code:
    length = getMinimalLength(a, b, c);
    the getMinimalLength function will be executed until it returns and the return value will be saved in length.
  2. To step into a line of code, for instance, when a function is called, use 's'.
    If you are unsure what is happening in your code, this is a best tool. Stepping into a line of code forces the debugger to step into any invoked functions. In our example, that means, the debugger will start debugging the code comprising the getMinimalLength function.
  3. To list a few lines of code use: 'list'.
    If you are unware which line of code the debugger is at, use list. This will list about ten lines of code showing the current line of code in the middle.
  4. To watch variable values, use 'p variable-name'.
    Debugging without being able to watch variable values is next to useless. This feature is central to any serious debugging. Let us assume, variable length is in the current scope and that we are debugging the line just after where getMinimalLength(..) function is called. To do this is as easy as:
    Code:
    p length


An Example:
For this example we will consider the following c++ program:
Code:
#include <iostream>
using namespace std;

long double fact (int n)
{
  int i;
  long double r = 1.0;
  
  for (i = 1; i <= n; i++)
    r = r * i;
  
  return r;
}  

int main()
{
  long double arr [100];
  int i, j, z;
  
  cout << "Start getting factorials from: ";
  cin >> z;
  
  cout << "Enter the number of iterations: ";
  cin >> j;
  
  if (j < 0 || j > 100)
  {
    cout << "Iteration count must lie within 0 and 100 including both ends\n";
    return 0;
  }  
  
  for (i = 0; i < j; i++)
  {  
    arr[i] = fact(z);
    z++;
  }  
  
  for (i = 0; i < j; i++)
    cout << arr[i] << '\n';
  return 0;
}
We will now compile the code. Assume the code is saved in a file named test07.cpp. Open a terminal, cd to the directory where you save test07.cpp, and invoke the g++ compiler in this way:
Code:
g++ -g test07.cpp -o test07
Take special notice of the -g directive. This tells the compiler that we want debugging information in our executable file.

Now, invoke the gdb debugger. The latter needs to know what executable you want to debug - pass its name as a parameter.
Code:
gdb test07
gdb will present its interface. This should look like the following:
Code:
$ gdb test07
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/edbarx/projects/test05/test07...done.
(gdb)
Suppose we want to debug the fact function. Line 7 in our code is a good place for a breakpoint because this will precede the portion of the function where the actual calculation takes place.

To insert a breakpoint we use the b command as follows:
Code:
(gdb) b 7
In the case our line of code we are interested in is in another file in the project, we would use the command as follows:
Code:
(gdb) b test07.cpp:7
The debugger will tell us that the breakpoint has been accepted.
Code:
Breakpoint 1 at 0x4009f3: file test07.cpp, line 7.
(gdb)
Now, we run the code:
Code:
(gdb) r
Starting program: /path-to-our-program/test07 
Start getting factorials from:
Follow, the program's prompts until the debugger halts the program at the breakpoint. Our program will display information similar to this.
Code:
(gdb) r
Starting program: /path-to-our-program/test07 
Start getting factorials from: 1
Enter the number of iterations: 2

Breakpoint 1, fact (n=1) at test07.cpp:7
7	  long double r = 1.0;
(gdb)
As you can see, the debugger duly stopped at the breakpoint. Typing n for next, moves the execution by one line as follows.
Code:
(gdb) n
9	  for (i = 1; i <= n; i++)
Another n will move the point of execution by another line.
Code:
(gdb) n
10	    r = r * i;
To see what values are in our variables we use the p command as follows:
Code:
(gdb) p i
$1 = 1
(gdb) p n
$2 = 1
(gdb) p r
$3 = 1
(gdb)
This is the first iteration where we are calculating the factorial of 1 which is 1. The for loop should exit immediately after this step. Let us see:
Code:
(gdb) n
9	  for (i = 1; i <= n; i++)
(gdb) n
12	  return r;
(gdb)
As you can confirm, the function is about to return the value r which should be 1. Let us check, if this is the case:
Code:
(gdb) p r
$4 = 1
... and we have r = 1 as expected.

To list the code where return r is situated, we use the list command:
Code:
(gdb) list
7	  long double r = 1.0;
8	  
9	  for (i = 1; i <= n; i++)
10	    r = r * i;
11	  
12	  return r;
13	}  
14	
15	int main()
16	{
(gdb)
Stepping further, ie using n some more times, the debugger will exit from the fact function returning to the main function as follows:
Code:
(gdb) n
13	}  
(gdb) n
main () at test07.cpp:35
35	    z++;
(gdb) n
32	  for (i = 0; i < j; i++)
(gdb)
Now, we will examine the second fact call which should return the factorial of 2. Note that 2! = 2. Please, note that the use of s, forces the debugger to move more slowly showing all steps even those behing the scenes. In this case, it is telling us that the returned value from fact is saved in the arr array. As you can see, sometimes, s, behaves like n. This depens on the complexity of the line at the point of execution. Function calls force the debugger to branch into them when s is used.

Code:
(gdb) s
34	    arr[i] = fact(z);
(gdb) s

Breakpoint 1, fact (n=2) at test07.cpp:7
7	  long double r = 1.0;
(gdb) s
9	  for (i = 1; i <= n; i++)
(gdb) s
10	    r = r * i;
(gdb) s
9	  for (i = 1; i <= n; i++)
(gdb) s
10	    r = r * i;
(gdb) p i
$5 = 2
(gdb) s
9	  for (i = 1; i <= n; i++)
(gdb) s
12	  return r;
(gdb) p r
$6 = 2
(gdb)
The result from the function is 2 as expected. To run the program until it exits or it meets another breakpoint use c (continue).
Code:
(gdb) c
Continuing.
1
2
[Inferior 1 (process 5331) exited normally]
Needless to state the obvious, the process number need not agree with mine.

To quit the debugger, use the q command as follows:
Code:
(gdb) q

Enjoy. :)

by rtmistler on Fri, 2015-02-27 08:43
I like what you've written and I'm a proponent of using GDB as well.

You should make that a blog entry.

Another thing you should note in there if you agree, is that GDB can be used through emacs. I don't use it much that way but it acts more like a real debugger and one can use the mouse for things directly within the screen, plus there are menus also accessible via the mouse. You also can pull up child windows for things like the stack and watch variables, memory views, etc.
  1. Edit a simple C source in emacs
  2. Issue compile command at the prompt, default is "make -k", just change that to be: gcc -ggdb -o <exe-name> <source-name>, this part is not necessary, but you can compile within emacs and a benefit is that you can browse for next error using the editor where it jumps right to each error and corrects line alignment if you edit/fix problems
  3. Issue debug command "gdb" at the prompt, it allows you to enter in options, but usually will pick good defaults and detect the executable file matching your source, especially if you compiled with it.
  4. From within the debugger you can do things like mouse left click near the left border of a source line to make a breakpoint, there are menu options to go, step, step-over, step-in, look at data, open sub-windows for things like watches, stack and so forth.
For those who can type and remember stuff, it's not always the best. Plus on a target system which may or may not have a display manager, knowing command line GDB is best.


  



All times are GMT -5. The time now is 07:23 AM.

Main Menu
Advertisement
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration