Sunday, May 13, 2012


ok..time to continue divulging!

Lets commence this post with conditional breakpoints.Now, where there are so many benefits, bp's themselves can become tedious sometime.We have to keep stepping,..stepping and stepping...
So,in situations, where we have an idea of what the error could not allocating memory to a pointer,crossing bounds of an array or stack overflow, we can avoid unnecessary breaks in our program, like at every iteration of a loop or at each call of a recursive function.So, we need to specify the condition for breaking at these points.Using 'conditional breakpoints' allow us to carry through this.
Syntax is just similar, except you have to supply a condition or an C-expression,which if true, will trigger the bp.
e.g. break 10 i >10 -> prog will stop at 10th line only if i exceeds 10.
This will most likely avoid all unnecessary stepping.
We can also use gdb variables for these conditions.Next two lines will explain this:
(gdb) set $i = 0
(gdb) break main: if ++$i == 10
':'->because we are specifying condition at a fn.Rest all is clear.

Now, there is something called 'breakpoint commands' in gdb.Yup, we can define a set of commands to be executed at a bp.This is a potent tool of gdb, I must say.
These commands can be any c expression or gdb commands.These commands can be used to turn on/off other breakpoints,jumping over a part of code, correct the code, to control automatically displayed expressions and many other things.
Two special commands of these are 'silent' & 'continue'.Silent causes gdb to skip the usual printing when arriving at a breakpoint, and continue, continues execution of your application.
So, proceeding with a basic example, following lines illustrate how to relate with other bp's:
We want to set bp on the print function in our program, but the condition is that run should stop on the print function that is present only in some function, say 'run'.Here is the solution:
(gdb) break print (bp #1)
(gdb) break run  (bp #2)
(gdb) commands
the following line will be displayed prompting you for the commands:
"Type commands for when breakpoint 2 is hit, one per line.
End with a line saying just "end"."
enter the following commands
>enable 1

(gdb) break 48    (bp #3)        Break at end of run function
(gdb) commands
Type commands for when breakpoint 3 is hit, one per line.
End with a line saying just "end".
>disable 1

Now, the execution stops at print only when it is discovered inside run function!.We are using silent and continue in these command sets, so that they doesn't need any intervention from the user.
With some modification, you can use the above function to skip over a part of code.Use gdb 'help' to get to know more about the commands("help commands").

Carrying on, Suppose you have forgotten to allocate memory to a struct pointer and you discovered it while running the program in gdb.Now what?
If your ans is--'Simple,jst open the file again,edit it,compile & run the gdb again'--yes,this post is specially for you..
Now this is the best part:fixing errors inside the debugger itself.Above example will best illustrate it:
your code:
#9    node *start;    //no memory allocated
#10    start->n=5; 

commands to rectify this:
(gdb) break 10        (bp #4)        Break on line just after the declaration
(gdb) commands
Type commands for when breakpoint 4 is hit, one per line.
End with a line saying just "end".
>print start = (node *) malloc(sizeof(node))

These breakpoint commands stop before the 10th line, allocate the memory, and continue with the 10th line, to chase the other bugs !. So, you fix the bug in the debugger and go on automatically.
BUT, important to note that this change will not be applied to the original file.So, don't forget to propagate the changes back to your original source code to permanently fix the problem!

So,that's it for this post.Next post will be devoted to the recursive programs(yes, I said 'recursive programs').
Sayonara till then :)


No comments: