GDB supports the command print to print out the content of variables. This works pretty well with all basic types, but becomes annoying at best with complex types like QString. GDB has its own macro language, so it is possible to write routines for printing these types.
When GDB starts it reads in the file $HOME/.gdbinit to load macros that should be available at runtime. In the following two sections I show a macro to print QString objects. If you copy this macro into your .gdbinit file it will be automatically available each time you call gdb.
Example session:
(gdb) print myString $2 = {static null = {<No data fields>}, static shared_null = {ref = {atomic = 39}, alloc = 0, size = 0, data = 0x82174ca, clean = 0, simpletext = 0, righttoleft = 0, asciiCache = 0, reserved = 0, array = {0}}, static shared_empty = {ref = {atomic = 1}, alloc = 0, size = 0, data = 0xf5f71aca, clean = 0, simpletext = 0, righttoleft = 0, asciiCache = 0, reserved = 0, array = {0}}, d = 0x8260b48, static codecForCStrings = 0x0} (gdb) printqstring myString (QString)0x8217658 (length=26): "this is an example QString" (gdb)
As you see above, print myString prints the QString as an object. Since the actual data is hidden in the element "d" it is not immediately visible - even print myString.d would not be very satisfactory, since QString stores its data in unicode format.
The form printqstring myString prints out a more readable version.
This macro was posted by David Faure to the KDE maillist in 2001:
define printqstring set $i=0 while $i < $arg0.d->len print $arg0.d->unicode[$i++].cl end end
It already prints out each character of the QString onto a single line.
A much refined version was posted by Arnaud de Muyser to the qt-interest list the same year:
define pqs set $i=0 set $unicode=$arg0.d->unicode printf "Getting QString...\n" while $i < $arg0.d->len set $c=$unicode[$i++].cl if $c < 32 printf "\\0%o", $c else if $c <= 127 printf "%c", $c else printf "\\0%o", $c end end end echo \n end
The internal representation of QString changed for Qt 4.x: the length is now stored in d->size and it uses UCS-16 instead of UTF-8 for internal storage. The fact that QStrings are now implicitly shared does not matter in this context though.
So this is my adapted version of the macro:
define printqstring printf "(QString)0x%x (length=%i): \"",&$arg0,$arg0.d->size set $i=0 while $i < $arg0.d->size set $c=$arg0.d->data[$i++] if $c < 32 || $c > 127 printf "\\u0x%04x", $c else printf "%c", (char)$c end end printf "\"\n" end
For KDE there is a collection of macros here.
The internal representation of QString changed again for Qt 5.x: it relies on QTypedArrayData to store its data. This is an internal class that allows to store shared array data very efficiently.
I made two adaptations of the macro:
define printqs5static set $d=$arg0.d printf "(Qt5 QString)0x%x length=%i: \"",&$arg0,$d->size set $i=0 set $ca=(const ushort*)(((const char*)$d)+$d->offset) while $i < $d->size set $c=$ca[$i++] if $c < 32 || $c > 127 printf "\\u%04x", $c else printf "%c" , (char)$c end end printf "\"\n" end define printqs5dynamic set $d=(QStringData*)$arg0.d printf "(Qt5 QString)0x%x length=%i: \"",&$arg0,$d->size set $i=0 while $i < $d->size set $c=$d->data()[$i++] if $c < 32 || $c > 127 printf "\\u%04x", $c else printf "%c" , (char)$c end end printf "\"\n" end
The difference is in how they access the array data of the string. The static version uses the blue code to access the data directly. It relies on some implementation details of the QArrayData class, therefore it may fail if some of the semantics or implementation details ever change. On the other hand the static version still works with core dumps or after the program crashed to analyze the wreckage. The dynamic version on the other hand uses the red code and relies on the (semi-)official interface of the QArrayData class. The downside is that this requires a dynamic call into the Qt code, which may fail (for some odd stack configurations), crash (in case you are analyzing a situation that leads to a real crash in QString), or simply refuse to work (core dumps and after the program already crashed).
In any case a warning: both versions take their time while printing strings. GDB has to dive very deep into the internals of Qt in order to extract the data, so printing even a very simple QString takes about 10 seconds.