LinuxQuestions.org
Review your favorite Linux distribution.
Go Back   LinuxQuestions.org > Blogs > rtmistler
User Name
Password

Notices


Rate this Entry

How To Debug Linux C Programs Effectively Using The Debugger

Posted 02-20-2019 at 02:23 PM by rtmistler
Updated 02-25-2019 at 10:23 AM by rtmistler

Introduction

The purpose of this blog is to provide a guide to Linux C (and C++) programmers as to how to use the Gnu DebuGger, GDB, effectively.

My reasons for writing this are because I participate a great deal in the Linux Questions site and view, plus respond to a number of questions in the Programming forum, and I notice that programmers of various experience seem to be lacking in either experience+knowledge, or initiative, to use the debugger.

This blog entry is a complement to my earlier blog Debugging C Programs Using GDB (Including core dumps!)

Audience and Prerequisites

Programmers writing C and C++ user space applications for Linux.

You must have Linux running, you must have the GDB tools installed, such as the build-essential package, and you should use emacs.

I fully understand that the reader may not like emacs. I didn't say you "must", I said you "should".

You absolutely do not have to use emacs, however for the purposes of this blog, I'll show you two examples, the first one using the command line only and a second one using emacs illustrating the benefits of having that user interface available.

Command Line Example From Start To Finish

Code to test:
Code:
void main(void)
{
    int a, b;

    b = 1;

    for (a = 0; a < 8; a++ ) {
        b = b * 2;
    }
}
Note:
Code does not require any standard libraries, we're not printing anything, we're not doing anything crazy here, and 2 raised to the 8th, by the way, is 256.

Raw Steps. More details to be shown later. Command line steps only. Items to enter are listed in bold:
  1. Use your favorite editor and copy/paste or type in the program above, please name it raise.c.
  2. Use the following command to compile: $ gcc -o raise -ggdb raise.c this should compile the program.
    Quote:
    Key Detail: -ggdb enables debugging
  3. Use GDB to debug the program. $ gdb raise you should get a (gdb) prompt.
  4. Set a breakpoint for line 8, the one stating b = b * 2; (gdb) b 8 the result should be the string, "Breakpoint 1 at 0x4004ea: file raise.c, line 8.", the hex address will be different on your machine.
  5. Run the program, (gdb) r the result will be some text, "Starting program: /home/rt/testcode/raise

    Breakpoint 1, main () at raise.c:8
    8 b = b * 2;"
You now have run your program and are stopped a line #8 ready to execute the line b = b * 2. What can you do from here? You can inspect the value of b, you can inspect the value of a, you can single step and then repeat an inspection of the value of b, you can also continue and potentially re-stop at this breakpoint. That all depends what the value of a is, which I've already told you, you can inspect.

How do you do these feats? By putting in commands at the (gdb) prompt like this:
p a
p b
s
p b
c
p a
p b
<and etc>

Explanation of the commands to the (gdb) prompt:

p a = print a
p b = print b
s = step
p b = print b
c = continue either forever until you loop forever, hit a breakpoint, or complete the program.
quit = quit the debugger and terminate any program in progress.

Please proceed and duplicate the commands to print variables, step, continue, and eventually quit once the program completes. Note that if you didn't cut/paste the sample program exactly, or if you added lines to it, such as additional lines for comments or for other lines reasons, then the breakpoint may have to be at a different line than line #8. Please check the line number where the b = b * 2; resides in your copy. If you copy/pasted exactly and didn't add anything, then it will be at line #8.
  • The breakpoint is within a loop.
  • When you run the program and hit the breakpoint, it is during the first iteration of that loop.
  • You can hit c to continue up to 7 more times and hit the same breakpoint.
  • If/when you hit c an 8th time, it will exit the loop and exit the program.
  • You'll see a report saying that an inferior process (process id # shown) has exited with code <number>.
  • Seeing as this is a void return function, the code value is not interesting for this case. The tools are extremely useful, but you need to "think" if what they are telling you is purposeful. All you needed here was that the program exited.
Using Emacs to Enhance the Experience

You can run GDB from within emacs and it will provide you with a graphical debug capability which will show the source file, an indicator where your point of execution is stopped at (when it is stopped). It can show you a variable watch window, a call stack window, along with other typical debug windows. It also gives you a command line interface to type the very same commands you used above, and will update the source frame to show progress as you hit breakpoints, or step through a program.

The primary benefit for me is that I can see my code as I step through it, and see the variable names, and the emacs interface automatically updates the source position.

How to use GDB from within emacs:
  1. Enter emacs and have the source file open for editing.
  2. Enter the emacs command mode, using ESC-x (hitting ESCAPE and then pressing 'x') you'll get a command prompt that appears like "M-x "
  3. Type in gdb and hit return, the command prompt line will appear like "Run gdb (like this): gdb -i=mi raise" implying that you are asking to run GDB of the code.
  4. Hitting return at this point will start GDB and get you a new emacs buffer showing the (gdb) prompt.
  5. From this point, you can type in the commands desired. For instance using the Gud menu to add breakpoints, watchpoints, and other items to perform symbolic debugging using a fairly good Integrated Development Environment (IDE).
  6. I myself have not used too many utilities from within emacs, I type a lot in the emacs command prompt and mainly view the source as it updates with a dual display of the source and the command line. You can however open a watch window, or view the call stack in a window. The full capabilities are things you can explore in more detail as you use the interface more.
Attached are some screen shots of GDB being used in emacs
Attached Images
File Type: png emacs-1.png (67.5 KB, 4 views)
File Type: png emacs-2.png (42.1 KB, 3 views)
Views 349 Comments 1
« Prev     Main     Next »
Total Comments 1

Comments

  1. Old Comment
    OMG, one could spend a lifetime learning emacs and still only scratch the surface. I'd never tried the gdb integration before. I've been missing out, it's awesome.

    Thanks for prompting me to try it.
    Posted 02-20-2019 at 06:32 PM by GazL GazL is offline
 

  



All times are GMT -5. The time now is 11:24 PM.

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
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration