Debugging is an essential part of the software development cycle, as even the most experienced programmers encounter bugs in their code. To effectively identify and fix these issues, developers rely on debuggers. One powerful debugger that C/C++ programmers can leverage is gdb. In this comprehensive guide, we will explore the basics of gdb and its useful features/options, providing you with the knowledge to debug your C programs in Linux effectively.
Understanding GDB Debugger Basics
At its core, gdb allows programmers to examine and analyze a program while it is executing. This capability enables developers to pinpoint the exact location of problems within their code. Before diving into the usage of gdb, there are a few key points to keep in mind.
Firstly, in order to utilize debuggers like gdb, you need to compile your program with debugging information. This information is necessary for the debugger to properly analyze your code. For example, when using the gcc compiler, which we will use in the examples later in this guide, you can include the “-g” command line option to generate the required debugging information.
Next, ensure that you have gdb installed on your Linux system. If you are using a Debian-based distribution such as Ubuntu, you can easily install gdb by running the following command:
sudo apt install gdb For installation on other distributions, refer to the relevant documentation.
Once you have compiled your program with debugging information and have gdb installed, you can execute your program in debugging mode using the following command:
gdb [prog-executable-name]
This command initiates the gdb debugger but does not launch your program. It is at this stage that you can define various debugging-related settings. For example, you can set breakpoints to pause program execution at specific line numbers or functions.
To launch your program, use the following gdb command:
run
If your program requires command line arguments, you can specify them after the “run” command, like this:
run [arguments]
GDB provides a wide range of useful commands that come in handy during the debugging process. We will explore some of these commands in the example section later in this guide.
A Practical Example of Using GDB
To illustrate the usage of gdb, let’s consider a simple example C program:
#include <stdio.h> int main() { int out = 0, tot = 0, cnt = 0; int val[] = {5, 54, 76, 91, 35, 27, 45, 15, 99, 0}; while(cnt < 10) { out = val[cnt]; tot = tot + 0xffffffff/out; cnt++; } printf("\n Total = [%d]\n", tot); return 0; }
In this code, the program iterates through the “val” array, assigns each value to the “out” variable, and calculates the “tot” variable by summing its previous value with the result of “0xffffffff/out.”
However, running this code produces the following error:
$ ./gdb-test Floating pointexception (core dumped)
To debug the code, we first need to compile it with the “-g” option. Use the following command:
gcc -g -Wall gdb-test.c -o gdb-test
Next, let’s run gdb and specify the executable we want to debug:
gdb ./gdb-test
Since the error we encounter is a “floating point exception,” we can infer that it occurs when performing a division by zero. To confirm this, we set a breakpoint at line number 11, where the division takes place:
(gdb) break11
Now, we can start the execution of the program:
run
When the breakpoint is hit for the first time, gdb displays the following output:
Breakpoint 1, main () at gdb-test.c:11 11 tot = tot + 0xffffffff/out; (gdb)
As shown in the output above, gdb highlights the line where the breakpoint was set. We can now print the current value of the “out” variable:
(gdb) print out $1 = 5 (gdb)
The value “5” is printed, indicating that everything is working correctly at this point. To continue the program execution until the next breakpoint, use the “c” command:
c
Repeat this process until you observe that the value of “out” becomes zero:
... ... ... Breakpoint 1, main () at gdb-test.c:11 11 tot = tot + 0xffffffff/out; (gdb) print out $2 = 99 (gdb) c Continuing. Breakpoint 1, main () at gdb-test.c:11 11 tot = tot + 0xffffffff/out; (gdb) print out $3 = 0 (gdb)
To confirm that this is indeed the cause of the exception, we can use the “s” (or “step”) command instead of “c” to execute line 11, where the program is currently paused, and see if the crash occurs:
(gdb) s Program received signalSIGFPE, Arithmetic exception. 0x080484aainmain() at gdb-test.c:11 11 tot= tot+0xffffffff/out;
As indicated by the highlighted output, this is indeed where the exception is thrown. Confirm this by running the “s” command again:
(gdb) s Program received signal SIGFPE, Arithmetic exception. 0x080484aa in main () at gdb-test.c:11 11 tot = tot + 0xffffffff/out;
By following this process, you can effectively debug your C programs using gdb.
Conclusion
This comprehensive guide has provided an overview of gdb and its usage in debugging C programs in Linux. While we have only scratched the surface of gdb’s capabilities, you now have a solid foundation to explore and utilize its features. Refer to gdb’s manual page for further details and experiment with the tool whenever you encounter debugging challenges in your code. Though gdb may have a learning curve, the effort is undoubtedly worth it.
Remember, debugging is an integral part of software development, and gdb empowers programmers with the ability to identify and resolve bugs efficiently. With its help, you can ensure that your C programs run smoothly and reliably.
Shape.host provides reliable and scalable Linux SSD VPS hosting services. With our secure cloud hosting solutions, your applications and websites will perform at their peak. Visit us at Shape.host to learn more about our services.