2014-01-30 27 views

回答

2

从GDB中了解Tcl_Obj *并不是特别容易,因为数据结构使用带覆盖类型的多态指针。 (是的,这是C魔法。)但是,肯定有一些事情可以尝试。 (我会假装下面的指针叫做objPtr,而且它的类型是Tcl_Obj *。)

首先,检查一下objPtr->typePtr指向什么,如果有的话。 A NULLobjPtr->typePtr意味着对象只是objPtr->bytes字段中有一些内容,它是一个UTF-8字符串,其中包含objPtr->length字节,\0objPtr->bytes[objPtr->length]。 A Tcl_Obj *应该从不同时具有其objPtr->bytesobjPtr->typePtrNULL

如果objPtr->typePtr不是NULL,它指向一个静态常量结构,该结构定义了Tcl_Obj *上的基本多态类型操作(认为它像是一个vtable)。最初你感兴趣的是name字段,这是一个可读的const char *字符串,它可能会帮助你很多。该结构中的其他内容包括如何复制对象以及如何序列化对象的定义。 (该objPtr->bytes真的持有序列化。)

objPtr->typePtr定义objPtr->internalRep的解释,这是一个C union是大到足以容纳两个通用指针(和其他一些东西之外,像longdouble;您还会看到Tcl_WideInt,这可能是long long,但取决于编译器)。这是怎么发生的是达到类型的实现,所以这里很难全面涵盖,但基本上这样的情况是,小整数具有有意义的objPtr->internalRep.longValue字段,浮点数具有有意义且更复杂的objPtr->internalRep.doubleValue类型挂在一边的结构。

与列表,该结构实际​​上挂落objPtr->internalRep.twoPtrValue.ptr1,是一个真正的struct List(在tclInt.h声明,是不是Tcl的公共API的一部分)。 struct List又有一个可变长度数组,其中elements字段;不要在那里修改,否则你会破坏事情。字典是类似的,但是使用struct Dict来代替(它包含散列表主题的变体),并且其在tclDictObj.c内被声明为只是;即使Tcl的其他实现也不能看到它们是如何在内部工作的。这是故意的。

如果您想要调试到Tcl_Obj *,您必须谨慎行事,查看typePtr,在必要时应用相关的强制转换,并确保您使用的Tcl的调试版本包含所有的符号和类型信息保存。

没有什么关于这一点,使调试整个值的数组特别容易。最简单的方法是打印对象的字符串来看,是这样的:

print Tcl_GetString(objv[1]) 

要知道,这样做可能引发的对象(包括内存分配)的序列化所以它绝对不是完美的。然而,这很容易做到。 (Tcl_GetString会根据需要生成序列化 - 将它存储在objPtr->bytes字段当然 - 并返回一个指针,这意味着返回的值是肯定是 UTF-8,那么Tcl在UTF-8上的内部变化略有不规范一对夫妇的,可能并不重要,以你现在的地方。)


请注意,您可以阅读一些从脚本这一信息的Tcl 8.6(目前推荐释放)与::tcl::unsupported::representation命令。正如你可以从名字中猜出的那样,它不被支持(因为它违反了很多Tcl的基本语义模型规则),但它可以在你打破附加gdb的大炮之前帮助调试。