如何在gdb中打印tcl_obj中的元素?

时间:2014-01-30 05:47:33

标签: gdb tcl

我正在调试c ++ - tcl接口应用程序,我需要查看Tcl_Obj objv的元素。 我试过print *(objv[1])等等,但它似乎没什么帮助。 有没有办法在gdb中看到Tcl_Obj个元素?

1 个答案:

答案 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->bytesobjPtr->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的大枪之前进行调试。