我正在调试c ++ - tcl接口应用程序,我需要查看Tcl_Obj
objv
的元素。
我试过print *(objv[1])
等等,但它似乎没什么帮助。
有没有办法在gdb中看到Tcl_Obj
个元素?
答案 0 :(得分:2)
从GDB理解Tcl_Obj *
并不是特别容易,因为数据结构使用带有遮蔽类型的多态指针。 (是的,这是一个棘手的C魔法。)但是,肯定有一些你可以尝试的东西。 (我假装指针在下面被称为objPtr
,并且它的类型为Tcl_Obj *
。)
首先,查看objPtr->typePtr
指向的内容,如果有的话。 NULL
objPtr->typePtr
表示对象只是在objPtr->bytes
字段中有一些内容,这是一个包含objPtr->length
字节的UTF-8字符串\0
objPtr->bytes[objPtr->length]
。 Tcl_Obj *
永远不会同时objPtr->bytes
和objPtr->typePtr
同时为NULL
。
如果objPtr->typePtr
不是NULL
,则它指向一个静态常量结构,该结构定义Tcl_Obj *
上的基本多态类型操作(将其视为类似于vtable)。您最初感兴趣的是name
字段;这是一个人类可读的const char *
字符串,它可能会帮助你很多。该结构中的其他内容包括如何复制对象以及如何序列化对象的定义。 (objPtr->bytes
字段确实包含序列化。)
objPtr->typePtr
定义objPtr->internalRep
的解释,它是一个C union
,足以容纳两个通用指针(以及其他一些东西,如{{1} 1}}和long
;您还会看到double
,这可能是Tcl_WideInt
,但这取决于编译器)。如何发生这种情况取决于类型的实现,因此很难在这里包含所有内容,但基本上小整数将long long
字段视为有意义的浮点数的情况将objPtr->internalRep.longValue
视为有意义,更复杂的类型将结构悬挂在一边。
使用列表,结构实际上会挂起objPtr->internalRep.doubleValue
并且实际上是objPtr->internalRep.twoPtrValue.ptr1
(在struct List
中声明并且不是Tcl的公共API的一部分)。 tclInt.h
又有一个可变长度数组,struct List
字段;不要在里面修改,否则你会破坏东西。字典类似,但使用elements
代替(其中包含哈希表主题的变体),并在struct Dict
内声明只是;甚至Tcl的其余部分也无法看到它们如何在内部工作。这是故意的。
如果要调试tclDictObj.c
,则必须仔细进行,查看Tcl_Obj *
,在必要时应用相关的强制转换,并确保使用的是保留所有符号和类型信息的Tcl。
没有什么可以使调试整个数组变得特别容易。最简单的方法是打印对象的字符串视图,如下所示:
typePtr
请注意,这确实会触发对象的序列化(包括内存分配),因此它绝对不是完美的。但是,这很容易做到。 (print Tcl_GetString(objv[1])
在必要时生成序列化 - 当然将其存储在Tcl_GetString
字段中 - 并返回指向它的指针。这意味着返回的值是肯定 UTF-8好吧,Tcl在UTF-8上的内部变化在几个地方略微非正规化,这对你来说可能并不重要。)
请注意,您可以使用objPtr->bytes
命令从Tcl 8.6(当前推荐版本)中的脚本中读取一些此类信息。正如您可以从名称中猜测的那样,它不受支持(因为它违反了大量Tcl的基本语义模型规则),但它可以帮助您在打破附加gdb的大枪之前进行调试。