GDB is one of the best debuggers available. GDB uses ptrace to trace the program's state. One needs to compile the program with -g option so that the debugger can get info of the symbol table. If the program is optimized while compilation, gdb shows a lot of interesting changes than the original flow we expect. Even some variables are removed from scope during optimization, if they are not utilized. GDB in one way also helps us to understand the functioning of compilers.
GDB supports to traverse a program line by line(with/without entering into subroutines/methods). It also supports creation of breakpoints. Since it has read the symbol table, it also supports printing the value of variables, provided they are not optimized out, at any point during execution.
This comes in handy when one looks into a big source code for a particular abnormality. I faced a weird issue with httpd and gdb really helped to find the handler which was responsible for the issue.