synthetic for std::wstring

Hi,

are there any Python scripts to debug a std::wstring (i.e. std::basic_string<int> in osx)?
It would be very useful, especially when debugging a vector of strings (i.estd::vector< std::wstring >)

After searching a while in the internet I found nothing, so I started to write my own Python class for generating synthetic children (exactly one chiled, i.e. the string itself),
but there are several problems I could not solve.

My test programm looks as follows:

     std::vector< std::wstring > aWideStringVector;
     aWideStringVector.push_back(L"Filter/EQ");
     aWideStringVector.push_back(L"Lowpass Filter");
     aWideStringVector.push_back(L"Wah Wah");
     aWideStringVector.push_back(L"Pitch Shift");
     aWideStringVector.push_back(L"Highpass Filter");
     aWideStringVector.push_back(L"Bandpass Filter");

I registered the synthetic children class with type synthetic add -x "^(std::)?basic_string<.+>" --python-class wstring.StdWStringSynthProvider but

frame variable aWideStringVector

gives me

(vector<std::basic_string<wchar_t>, std::allocator<std::basic_string<wchar_t> > >) aWideStringVector = {
}

and

frame variable aWideStringVector[0]

gives me

error: array index 0 is not valid for "(vector<std::basic_string<wchar_t>, std::allocator<std::basic_string<wchar_t> > >) aWideStringVector"

Am I doing something wrong?
Is it in general a good idea to debug a std::wstring with synthetic children?

thanks,
Nino

wstring.py (1.54 KB)

Hi. Replies are inlined.

Hi,

are there any Python scripts to debug a std::wstring (i.e. std::basic_string<int> in osx)?
It would be very useful, especially when debugging a vector of strings (i.estd::vector< std::wstring >)

After searching a while in the internet I found nothing, so I started to write my own Python class for generating synthetic children (exactly one chiled, i.e. the string itself),

Since you're only really producing one child value, it looks like you may want to provide a summary for the wstring instead of synthetic children.

but there are several problems I could not solve.

My test programm looks as follows:

   std::vector< std::wstring > aWideStringVector;
   aWideStringVector.push_back(L"Filter/EQ");
   aWideStringVector.push_back(L"Lowpass Filter");
   aWideStringVector.push_back(L"Wah Wah");
   aWideStringVector.push_back(L"Pitch Shift");
   aWideStringVector.push_back(L"Highpass Filter");
   aWideStringVector.push_back(L"Bandpass Filter");

I registered the synthetic children class with type synthetic add -x "^(std::)?basic_string<.+>" --python-class wstring.StdWStringSynthProvider but

You are trying to bind a synthetic children provider to *every* std::basic_string<T>? Why?
Again, I think a summary for std::wstring (and std::basic_string<wchar_t>) would be enough for the purpose.

frame variable aWideStringVector

gives me

(vector<std::basic_string<wchar_t>, std::allocator<std::basic_string<wchar_t> > >) aWideStringVector = {
}

What version of LLDB are you using? (LLDB has a "version" command you can use) This looks like an issue with the built-in synthetic children provider for class std::vector.

In order to test *your* wstring provider, you should have a single variable of type std::wstring and try to "frame variable" that one variable. Here, your entry point is the synthetic children provider for std::vector.

and

frame variable aWideStringVector[0]

gives me

error: array index 0 is not valid for "(vector<std::basic_string<wchar_t>, std::allocator<std::basic_string<wchar_t> > >) aWideStringVector"

again, what you're doing here is asking the std::vector synthetic children provider (built into LLDB) to provide you with child at index 0 - your wstring provider is not being invoked at this moment.

Am I doing something wrong?
Is it in general a good idea to debug a std::wstring with synthetic children?

1) Probably not - if you're using a recent version of LLDB then this issue might need further testing. Otherwise, it seems a good idea to retry this with TOT
2) Again, I would just use a summary string provider. On LLDB TOT, the attached Python file (which is a very slightly modified version of what you sent) works well in providing a summary for std::wstring

(lldb) command script import wstring.py
(lldb) type summary add --python-function wstring.wstring_summary std::wstring
(lldb) frame variable
(std::wstring) foo = hello world

wstring.py (448 Bytes)

Hi Enrico,

thank you for your help.

You’re welcome :slight_smile:

Since you’re only really producing one child value, it looks like you may want to provide a summary for the wstring instead of synthetic children.

Cool, thats exactly what I’m searching for, but I found only the synthetic children examples in the docu.

I think summaries are described here: http://lldb.llvm.org/varformats.html (there is an example about computing the area of a rectangle via Python and use that as a summary)

You are trying to bind a synthetic children provider to every std::basic_string? Why?

I am dealing with utf-8 utf-16 and utf-32 strings in my application and it would be great to be able to view all strings. Currently only the int version is implemented :frowning:

Are you going to have a way to distinguish the several encodings once you bind every std::basic_string to your summary function? If so, great :slight_smile:
A nice thing to be told about regexp, is that an exact match always wins over them, so you can make this binding and still get std::string (which is std::basic_string) for free with the default summary provider

Again, I think a summary for std::wstring (and std::basic_string<wchar_t>) would be enough for the purpose.

Yes

What version of LLDB are you using? (LLDB has a “version” command you can use) This looks like an issue with the built-in synthetic children provider for class std::vector.

LLDB-112

You may want to try on TOT

In order to test your wstring provider, you should have a single variable of type std::wstring and try to “frame variable” that one variable. Here, your entry point is the synthetic children provider for std::vector.

Thats what I’ve allready done with:

(lldb) type synthetic add “std::wstring” --python-class wstring.StdWStringSynthProvider
(lldb) frame variable aWideString
(std::wstring) aWideString = {
HELLO WORLD!!! = 0x0000004500000048
}

But when I have a vector of std::wstring the type of each element is std::basic_string<int, …> and the synth. children provider gets not invoked (thats why I tried to use “^(std::)?basic_string<.+>”, without success)

(lldb) frame variable aWideStringVector
(vector<std::basic_string<wchar_t>, std::allocator<std::basic_string<wchar_t> > >) aWideStringVector = {
[0] = {
_M_dataplus = {
_M_p = 0x0000000107300aa8
}
}
[1] = {
_M_dataplus = {
_M_p = 0x0000000107300bc8
}
}

This is promising, it looks like LLDB is displaying your vector items

again, what you’re doing here is asking the std::vector synthetic children provider (built into LLDB) to provide you with child at index 0 - your wstring provider is not being invoked at this moment.

The std::vector synthetic children provider returns the child at index 0. When lldb prints this child, the summary provider for wstring gets invoked, right?

Yes, right

  1. Probably not - if you’re using a recent version of LLDB then this issue might need further testing. Otherwise, it seems a good idea to retry this with TOT
  1. Again, I would just use a summary string provider. On LLDB TOT, the attached Python file (which is a very slightly modified version of what you sent) works well in providing a summary for std::wstring

Okay, the summary solution is obviously the better one. What is TOT? The latest lldb trunk version?

Yes, TOT is the latest trunk of LLDB that you download from svn and build yourself

(lldb) command script import wstring.py

(lldb) type summary add --python-function wstring.wstring_summary std::wstring

(lldb) frame variable

(std::wstring) foo = hello world

Unfortunately, this does not work for me. LLDB seems not to invoke the summary provider:

(lldb) command script import /Users/nino.kettlitz/wstring.py
(lldb) type summary clear
(lldb) type summary add --python-function wstring.wstring_summary “std::wstring”
(lldb) frame variable aWideString
(std::wstring) aWideString = {
_M_dataplus = {
_M_p = 0x0000000107300b68
}
}

Weird. But again, please use TOT before we explore other potential issues.

Hi Enrico,

I downloaded the latest lldb version from svn (117) and now evereything works as expected:

Glad to hear :slight_smile:

(lldb) type summary add --python-function wstring.wstring_summary “std::wstring”
(lldb) frame variable aWideString
(std::wstring) aWideString = HELLO WORLD!!!

When using vectors of std::wstring I had to register the complete template name of std::wstring, but than it worked perfectly.

It is a known scenario that depends on the debug info being emitted by the compiler. You are doing the right thing.
For std::string, we have a few workarounds in place so that users always see their strings no matter whether the long or short typename is used. For std::wstring we do not provide anything out-of-the-box, so you need to set things up this way yourself.

(lldb) type summary add --python-function wstring.wstring_summary “std::basic_string<int, class std::char_traits, class std::allocator >”
(lldb) frame variable aWideStringVector
(vector<std::basic_string<wchar_t>, std::allocator<std::basic_string<wchar_t> > >) aWideStringVector = {
[0] = Filter/EQ
[1] = Lowpass Filter
[2] = Wah Wah
[3] = Pitch Shift
[4] = Highpass Filter
[5] = Bandpass Filter
[6] = Combination
[7] = Notch Filter
[8] = Auto Filter
[9] = Distortion
}

Now I have two questions:

  • Can I replace the “official” lldb with the one I build, so that I can use it within Xcode?

Most probably it will not work, and Apple does not support it.

  • Is there a possibility to always load the type summary for wstring?

Yes. You can have a .lldbinit file in your home folder and LLDB will load commands from that file whenever it is launched.
An example is here: http://llvm.org/svn/llvm-project/lldb/trunk/examples/customization/pwd-cd-and-system/.lldbinit

thanks,
Nino

  • Enrico Granata