Wednesday, November 26, 2008

Gdb tricks

Yesterday I was debugging some curious bug in the Spring engine. I was playing a game of XTA and near the 51th minute the engine suddenly appeared to hang. So I fired up gdb, attached it to the process, and started to examine it. Now I wouldn't post here if I didn't learn some new things in gdb. That's what this post is about.


Static typing vs dynamic typing

By default, gdb uses some sort of static typing when examining data. If I point it at a memory location and tell it it contains a CObject pointer, then it will interpret it as a CObject pointer. Sometimes however, you have a list of polymorphous objects, and you want to know the actual type of the object being pointed to. This can be toggled on and off for all print commands using set print object on/off.

(gdb) p $99
$129 = (CObject *) 0xfe545f0
(gdb) set print object on
(gdb) p $99
$130 = (CUnit *) 0xfe545f0


Pretty printing


By default, gdb uses a very concise format for printing out objects. This may be good enough if you're looking at a tiny data structure, but for large structures it becomes illegible. You can, however, toggle pretty printing, which changes exactly this. Suddenly all members of a class are nicely indented, etc. Use set print pretty on/off for this.

Often when debugging, I find I'm absolutely not interested in the value of static members of classes. Even so, gdb still prints them out every time you print an instance of such class. This can be turned off using set print static on/off.


The poor man's loop applied to a linked list

I needed to go through a linked list yesterday, and was wondering how to do this without having to type a new print command every time. A little bit of googling brought me to this blog entry however, detailing how to loop through an array using the feature that pressing "return" on an empty line repeats the previous command. A similar thing can be done be used to loop through a linked list, in this example a std::list<CObject>. (Example is under the assumption of a 32 bit system.)

(gdb) set $node = 0x804a018
(gdb) p {CObject*} ($node + 8)
content of first node
(gdb) p {CObject*} (($node = *$node) + 8)
content of second node
(gdb)
content of third node
(gdb)
content of fourth node
...

I hope this helps you and I welcome all improvements and other tips!

2 comments:

  1. Nice to see my "poor man's loop" inspired you :). Your trick to traverse an std::list is quite neat, I shall remember it.

    ReplyDelete
  2. I tried summing up the contents of an array inside while loop in gdb, but it gave error.

    (gdb) set $i = 0
    (gdb) set $end = 156
    (gdb) set $sum = 0
    (gdb) while($i < $end)
    >$sum = $sum + this->array[$i]->length
    >end
    Undefined command: "$sum". Try "help".
    (gdb)


    Please can u help me with the problem.

    ReplyDelete