How to show JUCE strings in XCode's debugger:


#1

This sticky could eventually be used to create an FAQ of XCode and OSX related issues for compiling JUCE apps, but for the time being, it just answers one question:

Q: How can I see the values of JUCE strings in gdb?

A: (Thanks to Frank Luchs)

UPDATE! With the newest string changes (which mean that the string is stored internally as utf8, utf16 or utf32, this has all become a bit more straightforward. The new expression that you should enter into XCode instead of the one given above is just:

With this new version, XCode no longer needs to actually execute any code to get the result, so it seems to work more often than the old one (which never seemed to work properly for me).

Also, for the File class, you can use this expression:


#2

Brilliant, thanx a lot.


#3

Damn straight!


#4

Hi all,

 Recently I moved to leopard(10.5.6), i tried to use the above method for debugging but it didn't work, I had tried it on tiger(10.4.11) it had worked. I dont seem to understand it.

 Edit summary is always disabled on juce String, but on few juce::File variables it is enabled. I put this in "{(const char *)$VAR.getFullPathName().toUTF8()}:s" , it started showing "out of scope".

Do I have to make any changes to xcode preferences to enable debugging and also to see the values.

Any help would be appreciated.

regards.


#5

I’ve been using it on leopard with no problems, so not sure what to suggest…


#6

Hi jules,

Thanks for the prompt reply, I was able to figure out the problem.

there is a flag in the project setting “DEBUG_INFORMATION_FORMAT”, it should be set to either “dwarf” or “dwarf with dSym File”.

Debugging doesn’t work with “stubs”


#7

Ok, thanks. That’s a good tip.


#8

In case you use std::string, the format string would be: { $VAR.c_str()}:s


#9

I’ve got a set of GDB functions for printing JUCE String, StringArray, and StringPairArray objects in the debug console.

Copy and paste the code below into a file called ~/.gdbinit. It’ll give you three new commands in the debug console: ps, psa, and pspa. For example:

(gdb) ps myString
Hello, world!
(gdb) psa myStringArray
[ foo, bar, baz ]
(gdb) pspa myStringPairArray
{ foo: bar, baz: qux }

The functions below use toUTF8(), which means they’ll work even if you’ve set JUCE_STRING_UTF_TYPE to 16 or 32, or if you’re using an old version that uses juce_wchar, etc. Unfortunately, because StringArray doesn’t have any way to get a one-liner description without constructing a String to pass in, the functions have to grovel through the member variables instead.

The downside to calling functions is that in some situations you can’t call functions (if you’ve really hosed the stack, it might even crash gdb). So if you only care about recent versions and default settings, you can replace each instance of “.toUTF8()” with “.text” in the macros.

define ps
  if $argc == 0
    help ps
  else
    p $arg0.toUTF8()
  end
end

document ps
  Prints juce::String
  Syntax: ps <String>
end

define psa
  if $argc == 0
    help psa
  else
    set $size = $arg0.strings.numUsed
    set $i = 0
    printf "["
    while $i < $size
      if $i != 0
	printf ", "
      else
	printf " "
      end
      printf "%s", $arg0.strings.data.elements.data[$i].toUTF8()
      set $i++
    end
    printf " ]\n"
  end
end

document psa
  Prints juce::StringArray
  Syntax: psa <StringArray>
end 

define pspa
  if $argc == 0
    help pspa
  else
    set $size = $arg0.keys.strings.numUsed
    set $i = 0
    printf "{"
    while $i < $size
      if $i != 0
	printf ", "
      else
	printf " "
      end
      printf "%s: ", $arg0.keys.strings.data.elements.data[$i].toUTF8()
      printf "%s", $arg0.values.strings.data.elements.data[$i].toUTF8()
      set $i++
    end
    printf " }\n"
  end
end

document pspa
  Prints juce::StringPairArray
  Syntax: pspa <StringPairArray>
end 

As an alternative, you can add a little code into your program like this:

String desc(const String &s) { return s; }
String desc(const StringArray &sa) { String s; return sa.joinIntoString(s); }
String desc(const StringPairArray &spa) { return spa.getDescription(); }
// ... any other types you want to be able to print out, the way you want them formatted

Then in your .gdbinit:

define desc
  p desc($arg0).toUTF8()
end

You can even define an overload for desc(id), and then replace the built-in po with something that prints not only ObjC objects, but also JUCE (and other) C++ objects.


#10

Referring to the first post and at least with Xcode 4.2, the exact form to use should be:

If the const char* cast is missing, it won’t work.


#11

[quote=“hladik”]Referring to the first post and at least with Xcode 4.2, the exact form to use should be:

If the const char* cast is missing, it won’t work.[/quote]

Where exactly must this be written?

I’m trying to type it in after clicking “Edit Summary Format…” in the pop-up menu that appears if you click the variable in the list below the code during debugging.

It always worked in Xcode 3, but it is not working in Xcode 4 for me any more: whatever I write there, it doesn’t stick and the next time I go to open it again, the field for the formatter is empty. Must I enable something somewhere? I looked for the “Enable Data Formatters with Debug” menu item, but I haven’t found it.


#12

I somehow managed to get this working in 4.3, but after installing 4.3.1, it’s broken again! If anyone figures out how to do it, please let us know!


#13

FWIW, when I upgraded to 4.3.1, I had to clean out some duplicates from ~/Library/Developer/XCode/UserData/Debugger/CustomDataFormatters

It’s a simple XML file with a list of format strings and types.

Just the one format:

      <SummaryFormatter
         formatString = "{(const char *)$VAR.text.data}:s"
         type = "String">
      </SummaryFormatter>

Seems to work for me.


#14

Can someone post some instructions on how to do this (from scratch) in XCode 4?

Nothing above seems to be working.

Thanks!


#15

Yfede’s last suggestion works perfectly here in 4.3.2. Just saying…


#16

Uhh, yfede didn’t make a suggestion in his last post…

And jfitzpat’s suggestion doesn’t work…


#17

Sorry, you’re right, yfede quoted it. I meant {(const char*)$VAR.text.data}:s . Works well here.


#18

Since this feature has again stopped working for me lately, I tried editing the ‘CustomDataFormatters’ file as jfitzpat suggested.

<SummaryFormatter formatString = "{(const char *)$VAR.text.data}:s" type = "juce::String"> </SummaryFormatter>
This works (I’m using xcode 4.5.1), but only if I prepend the ‘String’ type with the juce:: namespace and only for locally declared variables. I wasn’t able to show a ‘const String&’ argument passed to a function. Any suggestion anyone?


#19

This works for me in xcode now ( {(const char *)$VAR.text.data}:s ), but I can't get lldb to work at all.  

In the meantime I can get lldb to display the data using something horrible like: 

mem read -fc -l20 -c20 `tests.text.data`

Is anyone else getting this single character business?  From the command-line

(lldb) frame variable *tests.text.data  -f s

(juce::CharPointer_UTF8::CharType) *tests.text.data = NULL

(lldb) frame variable *tests.text.data  -f c

(juce::CharPointer_UTF8::CharType) *tests.text.data = 't'

(lldb) 

(lldb) mem read -fc -l20 -c20 `tests.text.data`

0x101368020: teststring\0\0\0\0\0\0\a\0\0\0

The s option is clearly labelled as the format for a zero terminated string, but doesn't seem to work at all.   

 


#20

I use a very simple trick to solve this in lldb, using the toCFString method in the String class. Simply type

        print  mystringname.toCFString()

 

works every time