【问题标题】:How to print wchar_t string in lldb?如何在 lldb 中打印 wchar_t 字符串?
【发布时间】:2023-03-15 10:06:01
【问题描述】:

鉴于wchar_t* str; 指向一个以null 结尾的utf32(或utf16)字符串,我应该使用什么命令在lldb 中打印它?

【问题讨论】:

    标签: lldb


    【解决方案1】:

    我假设您想将其打印为 utf8。这有点涉及 - 您需要为 python 中的类型创建一个摘要提供程序,该提供程序返回一个 utf8 字符串进行打印。不过也不是特别复杂。创建一个像~/lldb/wcharsummary.py 这样的python 小文件,内容像

    import lldb
    def wchar_SummaryProvider(valobj, dict):
      e = lldb.SBError()
      s = u'"'
      if valobj.GetValue() != 0:
        i = 0
        newchar = -1
        while newchar != 0:
          # read next wchar character out of memory
          data_val = valobj.GetPointeeData(i, 1)
          size = data_val.GetByteSize()
          if size == 1:
            newchar = data_val.GetUnsignedInt8(e, 0)    # utf-8
          if size == 2:
            newchar = data_val.GetUnsignedInt16(e, 0)   # utf-16
          if size == 4:
            newchar = data_val.GetUnsignedInt32(e, 0)   # utf-32
          else:
            return '<error>'
          if e.fail:
            return '<error>'
          i = i + 1
          # add the character to our string 's'
          if newchar != 0:
            s = s + unichr(newchar)
      s = s + u'"'
      return s.encode('utf-8')
    

    将此加载到 lldb 并将此 python 函数设置为 wchar_t* 的摘要提供程序;最容易将其放入您的 ~/.lldbinit 文件中以供重复使用:

    command script import ~/lldb/wcharsummary.py
    type summary add -F wcharsummary.wchar_SummaryProvider "wchar_t *"
    

    然后给定一些在 32 位 wchar_t 中有一些 utf32 编码字符的源,

    NSString *str = @"こんにちは";  // 5 characters long
    wchar_t *str_utf32_wchar = (wchar_t*) [[str dataUsingEncoding:NSUTF32StringEncoding] bytes];
    

    lldb 会为我们以 utf8 格式打印它们:

    Process 22278 stopped
    * thread #1: tid = 0x1c03, 0x0000000100000e92 a.out`main + 146 at a.m:11, stop reason = step over
        #0: 0x0000000100000e92 a.out`main + 146 at a.m:11
       8    
       9        NSString *str = @"こんにちは";  // 5 characters long
       10       wchar_t *str_utf32_wchar = (wchar_t*) [[str dataUsingEncoding:NSUTF32StringEncoding] bytes];
    -> 11       printf ("0x%llx 0x%llx 0x%llx 0x%llx\n", (uint64_t) str_utf32_wchar[0], (uint64_t) str_utf32_wchar[1], 
       12                                                (uint64_t) str_utf32_wchar[2], (uint64_t) str_utf32_wchar[3]);
       13   
       14       [pool release];
    
    (lldb) fr va
    (NSAutoreleasePool *) pool = 0x0000000100108190
    (NSString *) str = 0x0000000100001068 @"こんにちは"
    (wchar_t *) str_utf32_wchar = 0x0000000100107f80 "こんにちは"
    
    (lldb) p str_utf32_wchar
    (wchar_t *) $0 = 0x0000000100107f80 "こんにちは"
    
    (lldb) x/16b `str_utf32_wchar`
    0x100107f80: 0xff 0xfe 0x00 0x00 0x53 0x30 0x00 0x00
    0x100107f88: 0x93 0x30 0x00 0x00 0x6b 0x30 0x00 0x00
    (lldb) 
    

    【讨论】:

    • 从 Xcode 4.6.2 开始,我需要做些什么来启用它吗?我将您的示例 str 和 str_utf32_wchar 复制/粘贴到我的项目中,但在 lldb 中打印后者时,除了内存地址之外,我仍然看不到任何其他内容。有什么方法可以验证找到wcharsummary.wchar_SummaryProvider 吗?
    • 我刚刚用 Xcode 4.6.2 的 lldb 试了一下。当您执行type summary add -F wcharsummary.wchar_SummaryProvider "wchar_t *" 时,请注意他的wcharsummary 部分指的是python 文件的文件名。在我的例子中,它被保存为~/lldb/wcharsummary.py,因此该文件中定义的函数被添加到python中的wcharsummary.命名空间下。如果您将 python 文件命名为不同的名称,则需要使用 type summary add 进行不同的注册。
    • 嗯,这正是我设置它的方式,ala this pastebin。仍然没有运气。无论如何,感谢您的帮助。
    • 您要打印 UTF32 数据吗?我认为原始脚本对于 unicode 字符的编码可以正常工作,但我认为它对于它声称支持的其他编码实际上不能正常工作——我只测试了 UTF32。
    • 是的,我尝试了你上面使用的示例 str / tr_utf32_wchar 以及我真正追求的是在 Mac 上调试 std::wstring 的。我认为 Xcode 启动时没有加载脚本,有什么方法可以检查吗?
    【解决方案2】:

    我稍微修改了 Jason 的代码以直接处理 wxString,而不必更改 int* 指针的摘要。

    通过在 Xcode 调试器控制台中键入 script 命令来测试它,然后粘贴下面的代码并按 ctrl-D。然后再次在 lldb 提示符处键入type summary add --python-function wxString_SummaryProvider "wxString"。适用于我的 wxWidgets 构建。

    def wxString_SummaryProvider(valobj, dict):
      e = lldb.SBError()
      charPointer = valobj.GetChildMemberWithName('m_impl').GetChildMemberWithName('_M_dataplus').GetChildMemberWithName('_M_p')
      valobj = charPointer
      s = u'"'
      if valobj.GetValue() != 0:
        i = 0
        newchar = -1
        while newchar != 0:
          # read next wchar character out of memory
          data_val = valobj.GetPointeeData(i, 1)
          size = data_val.GetByteSize()
          if size == 1:
            newchar = data_val.GetUnsignedInt8(e, 0)    # utf-8
          if size == 2:
            newchar = data_val.GetUnsignedInt16(e, 0)   # utf-16
          if size == 4:
            newchar = data_val.GetUnsignedInt32(e, 0)   # utf-32
          else:
            return '<error>'
          if e.fail:
            return '<error>'
          i = i + 1
          # add the character to our string 's'
          # print "char2 = %s" % newchar
          if newchar != 0:
            s = s + unichr(newchar)
      s = s + u'"'
      return s.encode('utf-8')
    

    【讨论】:

      猜你喜欢
      • 2021-11-21
      • 2021-04-28
      • 1970-01-01
      • 1970-01-01
      • 2017-04-05
      • 2023-03-30
      • 2020-01-24
      • 1970-01-01
      • 2015-12-31
      相关资源
      最近更新 更多