Friday, 10 August 2012

Debugging C++ using KDevelop

This is leading on from another post. Without being able to debug a program, it's very difficult to get anywhere or learn mostly from stupid mistakes and is a quintessential for making progress. Thankfully having a good IDE makes all the difference and I present to you how I use KDevelop to debug FreeCAD during development.

Debugging with KDevelop:

First ensure that you are compiling with debug symbols / information and set up KDevelop so that you can compile and launch FreeCAD successfully. Please see my previous post for information.

Open up KDevelop and then you can hit Debug.

The KDevelop workspace will now change to Debug Mode. It is more convenient to present tool panels that are more relevant to debugging than programming. The only frustration is that the Editor will not remember which file you have currently opened from the normal mode.

You can customise which tool panels are available by right clicking and selecting like so:

Useful tool panels for debugging are:

  • Variables
  • Breakpoints
  • Frame Stack

Creating and using breakpoints using KDevelop:

FreeCAD will load, but can take slightly longer since the GDB debugger is launched and use to monitor the FreeCAD executable. Breakpoints allow you to control the flow of program at any point in time where you can:

  • Pause on a line / statement (A statement is usually terminated by a semicolon, e.g. int i = 0;)
  • Run each statement one by one
  • Continue to the next breakpoint
By setting breakpoints, it allows the programmer to control to examine segments of code and check the behaviour of the program or complex algorithms. 

Setting a Break Point:

In the code editor window, look for an area of code that you want to examine and isolate a line where you want to pause the execution of the program. In KDevelop, click on the furthest area adjacent to the line to create a breakpoint.  KDevelop indicates when a break point is set by displaying a ladybird / ladybug.

Sometimes it is useful to set the editor to visualise the line numbers which can be done by enabling the option at Editor->View->Show Line Numbers

Now, run the program normally and attempt to 'trigger' the break point by performing an action that will cause the segment of code you want to be executed - sometimes that's not always straightforward! When a break point is hit, KDevelop will highlight this.

We have paused the execution of the program. We can control the flow by using the debug toolbar at the top.

Importantly, Step Over will run to the next statement on line 43 - this would be std::string path = hGrp...

Continue will run till it reaches the next Break Point, this could be set in the same segment of code, or in another completely different area of the program. So in the example below clicking continue would run all the program till it reaches line 48 - args.push_back(QString...

The other two I rarely use, but they will enter a function or exit a function, but often I found going directly into these function sources and setting my own break points are easier. All break points are shown in the Break Points tool view. These can be toggle on or off and can be deleted. 

*Useful hints:

  • Remove all previous break points if you have recompiled FreeCAD with modifications to the code, or even just launching the program. I find it much quicker to launch FreeCAD in debug mode by doing this.
  • The more editors tabs you have open, it appears to take longer to launch and consumes more memory.

Making use of Break Points:

When we stop the flow of the program, we can examine the current state of the 'stack'. KDevelop makes this exceptionally easy. We can find the current values of variables or properties of classes/objects. This can be done by highlighting over a variable or object using your cursor:

Alternatively you may use the Variables Tool View to examine all the variables accessible within the 'current scope' or on the stack. It presents a hierarchical tree and can present meaningful data for known variables types and classes within the project tree:

All it takes now is some logic and wit to figure out what is causing the problem. Sometimes it can be blindingly obvious and for other times it can take hours :( The more practice you get the easier it seems to become.

The Frame Stack:

This is most useful when you have a sudden crash.

 Conventionally a stack can be imagine like a stack of  dirty plates at a restaurant. When you enter a new program scope (e.g. run a body of a function) you add on a dirty plate (so the dirty food represents variables). Conversely, exiting a program scope you clean the plate and take off the stack of dirt dishes. I tend to imagine it like an onion, you must peel a layer to access the inner layer. 

You can view the current state of the stack using the Frame Stack Tool View, when a program crashes GDB will display the state of the frame stack to help identify where the crash occurred. This will be at Depth 0, but logically you may have to look higher up to understand why. Usually the current state of the stack variables can also be accessed using the Variables tool view. (*precaution GDB will crash if you attempt to access a null pointer)

Below the current program is on line 49 within the LuxRenderProcess::initialiseSettings method. This method was called in Renderer.cpp on line 363. It is simple as that. 

Hopefully this guide will help you get debugging and make learning how to program c++ within FreeCAD that much easier!

No comments:

Post a Comment