Fortunately gdb has some scripting support to automate the process of ripping the string apart to display. After some searching I found this version. (Minor conversion to kde 2.3.2, the .cl in unicode[$i++].cl is changed to .ucs for later versions of qt). The script can be found on the kde web site kde-devel-gdb along with some other qt related gdb scripts.
Note: When using the scripts make sure the really long string constant is all on one line without any whitespace. Web browsers don't wrap long words so I manually put in some line breaks. The scripts can be downloaded as a text file kde_gdb.txt and my_gdb.txt. Move the file to .gdbinit in your home directory for gdb to read the function each time you start gdb.
define printqstring set $i=0 set $out="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" set $cur=0 set $s = $arg0 while $i < $s.d->len set $out[$cur++] = (char)($s.d->unicode[$i++].cl & 0xff) if $cur >= 40 p $out set $cur = 0 set $out="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" end end if $cur < 40 p $out end end
I have in my notes that I was viewing a 4536 character string, the important thing is it is somewhat long. The above version took 54 seconds to display the string. It would visibly pause between each line of output, I did say that gdb had scripting, I didn't say that it was fast. This is the first time I had really played with gdb scripts, and I was determined to optimize things a little.
define printqstring set $i=0 set $length=60 # hold up to 80 characters at a time set $out="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" set $a = &$arg0.d->unicode[0].cl set $stop = $arg0.d->len # find a multiple of $length to print set $whole = $arg0.d->len/$length set $whole *= $length set $cur = 0 set $incur = 0 # take care of multiples of $length while $incur < $whole set $cur = 0 while $cur < $length set $out[$cur++] = $a[$incur++ <<1] end output $out end set $out="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" set $cur = 0 while $incur < $stop set $out[$cur++] = $a[$incur++ <<1] end if $out[0] printf "\n" output $out end printf "\n" end
My script is longer, has a nested loop, and another loop while the original script only had one loop, but mine is faster, much. My script takes some work setting up variables, but the critical section of my script has less statements to execute, only two vs three, and each statement is less complicated because there are less checks and less work to do in that section.
At time time it was taking something like 12 seconds to print the same 4536 character string. That comes out to about 4.5 times faster. More recently I did some more time tests between both scripts.
new code 5.7 seconds for 4K
old code 16 seconds for 4K
New code 55 seconds for a 40K string.
Old code 152 seconds for 40K string.
I'm now running gdb version 5.2.90_2002-11-20-cvs-debian, I don't know what version I was running at the time, but it looks like they must have improved script performance, between two and three times faster. My version of the script might not be as portable since I made some more assumptions than the original script, but it works for me and is much faster.
One note of caution that holds for both strings, gdb allocates memory for each array assigned in the scripts from the program's memory space and never gives it back, it is just a memory leak. The same holds for malloc and free. You can call the malloc and free functions from the scripts, but from my tests free doesn't do anything, or at least it doesn't return the memory to the program which to me means it doesn't do anything, so I'm just assigning the array. Maybe I should use this opportunity to note that my version of the script only allocates two arrays each time it is run where as the original script allocates an array per line of output.