I am debugging a c++-tcl interface application and I need to see the elements of Tcl_Obj
objv
.
I tried doing print *(objv[1])
and so on but it doesnt seem helping.
Is there any way to see Tcl_Obj
elements in gdb?

- 133,037
- 18
- 149
- 215

- 693
- 3
- 14
- 27
1 Answers
It's not particularly easy to understand a Tcl_Obj *
from GDB as the data structure uses polymorphic pointers with shrouded types. (Yeah, this is tricky C magic.) However, there are definitely some things you can try. (I'll pretend that the pointer is called objPtr
below, and that it is of type Tcl_Obj *
.)
Firstly, check out what the objPtr->typePtr
points to, if anything. A NULL
objPtr->typePtr
means that the object just has something in the objPtr->bytes
field, which is a UTF-8 string containing objPtr->length
bytes with a \0
at objPtr->bytes[objPtr->length]
. A Tcl_Obj *
should never have both its objPtr->bytes
and objPtr->typePtr
being NULL
at the same time.
If the objPtr->typePtr
is not NULL
, it points to a static constant structure that defines the basic polymorphic type operations on the Tcl_Obj *
(think of it as being like a vtable). Of initial interest to you is going to be the name
field though; that's a human-readable const char *
string, and it will probably help you a lot. The other things in that structure include a definition of how to duplicate the object and how to serialize the object. (The objPtr->bytes
field really holds the serialization.)
The objPtr->typePtr
defines the interpretation of the objPtr->internalRep
, which is a C union
that is big enough to hold two generic pointers (and a few other things besides, like a long
and double
; you'll also see a Tcl_WideInt
, which is probably a long long
but that depends on the compiler). How this happens is up to the implementation of the type so it's difficult to be all-encompassing here, but it's basically the case that small integers have the objPtr->internalRep.longValue
field as meaningful, floating point numbers have the objPtr->internalRep.doubleValue
as meaningful, and more complex types hang a structure off the side.
With a list, the structure actually hangs off the objPtr->internalRep.twoPtrValue.ptr1
and is really a struct List
(which is declared in tclInt.h
and is not part of Tcl's public API). The struct List
in turn has a variable-length array in it, the elements
field; don't modify inside there or you'll break things. Dictionaries are similar, but use a struct Dict
instead (which contains a variation on the theme of hash tables) and which is declared just inside tclDictObj.c
; even the rest of Tcl's implementation can't see how they work internally. That's deliberate.
If you want to debug into a Tcl_Obj *
, you'll have to proceed carefully, look at the typePtr
, apply relevant casts where necessary, and make sure you're using a debug build of Tcl with all the symbol and type information preserved.
There's nothing about this that makes debugging a whole array of values particularly easy. The simplest approach is to print the string view of the object, like this:
print Tcl_GetString(objv[1])
Be aware that this does potentially trigger the serialization of the object (including memory allocation) so it's definitely not perfect. It is, however, really easy to do. (Tcl_GetString
generates the serialization if necessary — storing it in the objPtr->bytes
field of course — and returns a pointer to it. This means that the value returned is definitely UTF-8. Well, Tcl's internal variation on UTF-8 that's slightly denormalized in a couple of places that probably don't matter to you right now.)
Note that you can read some of this information from scripts in Tcl 8.6 (the current recommended release) with the ::tcl::unsupported::representation
command. As you can guess from the name, it's not supported (because it violates a good number of Tcl's basic semantic model rules) but it can help with debugging before you break out the big guns of attaching gdb.

- 133,037
- 18
- 149
- 215