18.6. The KDevelop Debugger

In the set of tools available for developers under the GNU license, there is a debugger, the gdb. gdb itself is a command-line tool like g++ and gcc and is used to monitor applications during runtime. The application binary therefore has to include runtime information for the debugger, which can be turned on during compilation. Then gdb will deliver as much information about your application as available: addresses, method names, object values, location of methods in your source files, and much more. However, to make the best use of it, a lot of freely available GUI front ends are provided, such as ddd or kdbg, which let you run your application with gdb and display the runtime information delivered by gdb. KDevelop, however, contains a new internal debugging front end to gdb that lets you use all features within the same environment so that you don't have to switch between your coding editor and the debugger application. Its integration is seamless and easy to use, and you are still provided the possibility to use an external debugging front end as a tool in the Tools window.

18.6.1. Setting the Debugger Options

The debugger settings, like all other KDevelop configuration options, are located in KDevelop Setup, which can be accessed via the Options menu. Select the debugger tabulator to change the debugging settings.

There you can select between the default use of the internal KDevelop debugger or using an external debugger with the debugger name you want to use (ddd or kdbg).

Next, three major settings for the internal debugger are worth a closer look. First is the option to set Pending Breakpoints. A breakpoint is a mark in the source code at a certain line where you want the debugger to stop your application—for example, when you're searching for a segmentation fault or you want to inspect how often your application will call the same method to increase the performance when you know how to reduce the number of times a method gets called. Now, applications often make use of libraries that they are linked to. Although static libraries are included into the binary, dynamic libraries such as the KDE and Qt libraries are loaded when an application calls a method that is in one of these libraries. That means as long as a method that is placed in a library didn't get called, the library won't be loaded. When you want to set a breakpoint exactly at a method call that is in a library, gdb can't set it if the library isn't in the system's memory. The Pending Breakpoint option helps here because it deactivates the breakpoint as long as the library hasn't been loaded, and it tries to activate it as soon as the library is available in memory.

The second option that is very important is the floating toolbar. In debugging mode of KDevelop, this brings up a separate little toolbar window that contains the debugging commands as icons and that will stay on top. This is a nice feature that makes debugging easier, and you can still monitor the source code in KDevelop behind your application window (see Figure 18.11). There is also the option to use a separate I/O window for applications that make use of command-line input calls, such as cin and fgets. In that case, checking the floating toolbar is again a good option so that your input window doesn't get obscured when activating debugging commands.

18.6.2. How to Enable Debugging Information

To debug your application, all you have to do is to tell the compiler to include debugging code into the binary that serves as a reference from the object code to the original source code so that breakpoints can be set and monitored.

For this, open the Project Options dialog available in the Project menu. Switch to the compiler options tabulator and check the Generate Debugging Information option together with the debugging level. By default, debugging is turned on at project creation, so you shouldn't worry if your application loads a bit slower when running a normal test. To see how it will perform when compiled normally, deselect this option and enable optimization instead, which can be done on the same page. A commonly used optimization level is -02, which will work in most cases, but you're on the safe side using -01.

Figure 18.11. The KDevelop debugger is your gateway to the CPU and memory usage of your application. It allows you to monitor your program's execution line by line along the source code.

18.6.3. Running a Debugging Session

To actually use the debugger, you have to run your application within gdb. For that, use the Debug menu, which offers the normal Start operation and advanced selection of starting methods, such as appending arguments or attaching your application to another process. Notice that you have to set a breakpoint before starting the debugger; otherwise, your program won't stop! Setting breakpoints is one of the easiest tasks. The editor windows have a gray pane on the left; you just have to click the line on which you want to stop, and a breakpoint symbol is placed. The context menu over this pane offers advanced options to the debugger as well as switching between breakpoint and bookmark modes. Then the debugger will start your program and the debugging options and windows will be available. These are

  • Run—Executes or continues the program.

  • Run to Cursor—Executes the program until the current cursor position in the source code is reached.

  • Step Over—Executes one line of code and will stop the application on the next line.

  • Step Over Instruction—Executes exactly one machine instruction. The assembler code that is executed and where the machine instructions can be monitored is the Disassemble tab in the output window.

  • Step In—Executes one line of code where you will step into the method call, if necessary.

  • Step In Instruction—Executes one machine instruction as described previously.

  • Step Out—Runs to the end of the stack frame and out of the function the application is currently processing.

  • Viewers—Opens the debugging viewers dialog where you can inspect a variety of values of the running application, such as the disassembled code, memory status, library status, and CPU register states.

  • Stop—Stops the application execution.

  • Exit—Stops the application execution and exits the debugger.

With these options, you can control the processing of your application's execution at runtime. On the other hand, you certainly don't want only to hop through the source code, but you might also want to know which values your variables have during execution time. This is the easiest way to find the cause of a segmentation fault. To those who aren't experts with programming yet, you may have encountered a program suddenly exiting without you wanting it to exit. It is just gone and your work is lost. The cause of this is most often a segmentation fault. That means that the computer tries to access an object the program refers to, but the object doesn't exist. The program will crash in that case because it violates the memory protection by wanting to access an address area that it isn't allowed to. Development of C++ and C applications often involve the use of pointers to objects that are the cause of most segmentation faults; therefore, you surely want to watch if a pointer is valid during runtime. The KDevelop debugger now offers the Watch functionality for variables. In the VAR tabulator, you get a Tree View of all objects of the application and their status. There, you can select which variables you want to watch. This is often useful for local variables within a method call you're monitoring. Variables to be watched can be added to the Watch section by using the input field on the bottom of the VAR window or by a context menu within the tree.

Now you should be able to successfully run and debug your application and make it as safe as it can be. Keep in mind that users expect your application to be stable, and they certainly don't want to lose their work—the same as you don't want your IDE to crash while you're programming!