Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Debugging 声明大小字符串类型的lldb摘要字符串_Debugging_Lldb - Fatal编程技术网

Debugging 声明大小字符串类型的lldb摘要字符串

Debugging 声明大小字符串类型的lldb摘要字符串,debugging,lldb,Debugging,Lldb,我想为nim语言的内置字符串类型提供一个格式化程序,但不知何故,我未能提供它。Nim编译为c,您在这里看到的字符串类型的c表示形式: #if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) # define SEQ_DECL_SIZE /* empty is correct! */ #else # define SEQ_DECL_SIZE 1000000 #endif typedef char NIM_CHAR; ty

我想为nim语言的内置字符串类型提供一个格式化程序,但不知何故,我未能提供它。Nim编译为c,您在这里看到的字符串类型的c表示形式:

#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)
#  define SEQ_DECL_SIZE /* empty is correct! */
#else
#  define SEQ_DECL_SIZE 1000000
#endif
typedef char NIM_CHAR;
typedef long long int NI64;
typedef NI64 NI;
struct TGenericSeq {NI len; NI reserved; };
struct NimStringDesc {TGenericSeq Sup; NIM_CHAR data[SEQ_DECL_SIZE]; };
下面是我在lldb会话中尝试的输出:

(lldb) frame variable *longstring
(NimStringDesc) *longstring = {
  Sup = (len = 9, reserved = 15)
  data = {}
}
(lldb) frame variable longstring->data
(NIM_CHAR []) longstring->data = {}
(lldb)  type summary add --summary-string "${&var[0]%s}" "NIM_CHAR []"
(lldb) frame variable longstring->data
(NIM_CHAR []) longstring->data = {}
(lldb)  type summary add --summary-string "${var%s}" "NIM_CHAR *"
(lldb) frame variable longstring->data
(NIM_CHAR []) longstring->data = {}
(lldb) frame variable &longstring->data[0]
(NIM_CHAR *) &[0] = 0x00007ffff7f3a060 "9 - 3 - 2"
(lldb) frame variable *longstring
(lldb)  type summary add --summary-string "${var.data%s}" "NimStringDesc"
(lldb) frame variable *longstring
(NimStringDesc) *longstring = NIM_CHAR [] @ 0x7ffff7f3a060
(lldb)  type summary add --summary-string "${&var.data[0]%s}" "NimStringDesc"
(lldb) frame variable *longstring
(NimStringDesc) *longstring = {
  Sup = (len = 9, reserved = 15)
  data = {}
}
(lldb) 

我简直无法管理,输出将只是被解释为
'\0'
终止的c字符串的数据。

您尝试过的摘要字符串语法(根据设计)没有c语法丰富

由于您使用的是零大小的数组,我认为我们没有任何神奇的规定将其视为指向字符串的指针。您可能想提交一个关于它的bug,但在这种情况下,它是否会帮助您是有争议的。因为您的字符串是长度编码的,所以它实际上不需要以零结尾,这是LLDB能够理解的唯一提示,即何时停止读取指向字符的指针

在您的情况下,您将不得不求助于Python格式化程序

您需要的是:

  • 字符串缓冲区的内存位置
  • 字符串缓冲区的长度
  • 从内存中读出数据的过程
这是一个非常小的Python代码段,可以实现这一点——我也会给您一些增强建议,但让我们从基础开始:

def NimStringSummary(valobj,stuff):
    l = valobj.GetChildMemberWithName('Sup').GetChildMemberWithName('len').GetValueAsUnsigned(0)
    s = valobj.GetChildMemberWithName('data').AddressOf()
    return '"%s"'% valobj.process.ReadMemory(s.GetValueAsUnsigned(0),l,lldb.SBError())
如您所见,首先它读取长度字段的值; 然后读取数据缓冲区的地址;然后,它使用值来自的进程来读取字符串内容,并以引号返回

现在,这是一个概念证明。如果在生产中使用它,您会很快遇到一些问题:

如果您的字符串缓冲区尚未初始化,并且它显示缓冲区的大小为20GB,该怎么办?您将不得不限制您愿意读取的数据的大小。对于类似字符串的类型,它具有(char*,std::string,Swift.string,…)的内置知识,LLDB打印出被截断的缓冲区,后跟…,例如

  (const char*) buffer = "myBufferIsVeryLong"...
如果指向数据的指针无效怎么办?您应该检查s.GetValueAsUnsigned(0)实际上不是零-如果是,您可能希望打印一条错误消息,如“null buffer”

另外,这里我只是传递了一个SBError,然后忽略它——最好传递一个,然后检查它 总而言之,你最终会得到这样的结果:

import lldb
import os

def NimStringSummary(valobj,stuff):
    l = valobj.GetChildMemberWithName('Sup').GetChildMemberWithName('len').GetValueAsUnsigned(0)
    if l == 0: return '""'
    if l > 1024: l = 1024
    s = valobj.GetChildMemberWithName('data').AddressOf()
    addr = s.GetValueAsUnsigned(0)
    if addr == 0: return '<null buffer>'
    err = lldb.SBError()
    buf = valobj.process.ReadMemory(s.GetValueAsUnsigned(0),l,err)
    if err.Fail(): return '<error: %s>' % str(err)
    return '"%s"' % buf

def __lldb_init_module(debugger, internal_dict):
    debugger.HandleCommand("type summary add NimStringDesc -F %s.NimStringSummary" % os.path.splitext(os.path.basename(__file__))[0])
导入lldb
导入操作系统
def NimStringSummary(valobj,stuff):
l=valobj.GetChildMemberWithName('Sup')。GetChildMemberWithName('len')。GetValueAsUnsigned(0)
如果l==0:返回''''
如果l>1024:l=1024
s=valobj.GetChildMemberWithName('data').AddressOf()
地址=s.GetValueAsUnsigned(0)
如果addr==0:返回“”
err=lldb.SBError()
buf=valobj.process.ReadMemory(s.GetValueAsUnsigned(0),l,err)
if err.Fail():返回“”%str(err)
返回''%s''%buf
def _lldb _init_模块(调试器,内部命令):
debugger.HandleCommand(“类型摘要添加NimStringDesc-F%s.NimStringSummary”%os.path.splitext(os.path.basename(_文件__))[0])
另外一个技巧是_lldb_init_module函数——每当您“命令脚本导入”python文件时,lldb就会自动调用该函数。这将允许您将“命令脚本导入”添加到~/.lldbinit文件中,并在所有调试会话中自动获取格式化程序


希望这有帮助

谢谢你的回答,这对我帮助很大。我会尽快尝试一下。但是在您已经访问Sup成员之后,您正在检查
数据的地址
0
。数据的地址永远不能是
0
,因为字符串是直接嵌入Sup之后的,它不是指针。我保持原样,因为这是我在Stackoverflow上得到的最好答案,非常感谢。一切正常,解释得很好。恩里科-这是纯金。谢谢你写这篇文章!