Tested on Linux:
Linux XXX YYYY #5 SMP Mon Nov 16 15:30:32 PST 2009 x86_64 x86_64 x86_64 GNU/Linux
Compiled tcl8.5.9 like this:
configure --prefix=/home/sehmann/tcltk-8.5.9 --enable-shared --enable-64bit --enable-symbols
make install
These problems do not occur on tcl8.4.9, we are trying to upgrade and this is a blocker.
Case 1) This is the case for my application
C code:
Tcl_Obj* cmdArgs[3];
cmdArgs[0] = Tcl_NewStringObj("::testtest", -1);
cmdArgs[1] = Tcl_NewStringObj("::testtest2", -1);
cmdArgs[2] = Tcl_NewIntObj(1);
int result = Tcl_EvalObjv(interp, 3, cmdArgs, TCL_EVAL_GLOBAL);
TCL code:
proc testtest2 {} {
error "this is a test error"
}
proc testtest {foo bar} {
$foo
}
Gives:
Error message:
UpdateStringProc should not be invoked for type cmdName
Program received signal SIGABRT, Aborted.
Stack trace:
#0 0x0000003eb752e21d in raise () from /lib64/tls/libc.so.6
#1 0x0000003eb752fa1e in abort () from /lib64/tls/libc.so.6
#2 0x00007ffff7e85a7d in Tcl_PanicVA (format=0x7ffff7ed4870 "UpdateStringProc should not be invoked for type %s", argList=0x7fffffff9c60)
at /home/sehmann/tcl8.5.9/unix/../generic/tclPanic.c:103
#3 0x00007ffff7e85b57 in Tcl_Panic (format=0x7ffff7ed4870 "UpdateStringProc should not be invoked for type %s")
at /home/sehmann/tcl8.5.9/unix/../generic/tclPanic.c:132
#4 0x00007ffff7e82d94 in Tcl_GetStringFromObj (objPtr=0x170c5b0, lengthPtr=0x7fffffff9da4)
at /home/sehmann/tcl8.5.9/unix/../generic/tclObj.c:1626
#5 0x00007ffff7e73d47 in UpdateStringOfList (listPtr=0xec4dd0) at /home/sehmann/tcl8.5.9/unix/../generic/tclListObj.c:1872
#6 0x00007ffff7e82da6 in Tcl_GetStringFromObj (objPtr=0xec4dd0, lengthPtr=0x7fffffff9e7c)
at /home/sehmann/tcl8.5.9/unix/../generic/tclObj.c:1629
#7 0x00007ffff7de411d in Tcl_EvalObjv (interp=0x504640, objc=3, objv=0x7fffffff9f10, flags=131072)
at /home/sehmann/tcl8.5.9/unix/../generic/tclBasic.c:3919
Case 2) This is disturbing
C code:
Tcl_Obj* cmdArgs[3];
cmdArgs[0] = Tcl_NewStringObj("::testtest", -1);
cmdArgs[1] = Tcl_NewStringObj("::testtest2", -1);
cmdArgs[2] = Tcl_NewIntObj(1);
int result = Tcl_EvalObjv(interp, 3, cmdArgs, TCL_EVAL_GLOBAL);
TCL code:
proc testtest2 {} {
error "this is a test error"
}
proc testtest {foo bar} {
testtest2
}
Gives:
Error message:
Program received signal SIGSEGV, Segmentation fault.
Stack trace (infinite recursion):
#0 0x00007ffff7e73c47 in UpdateStringOfList (listPtr=0xec4dd0) at /home/sehmann/tcl8.5.9/unix/../generic/tclListObj.c:1848
#1 0x00007ffff7e82da6 in Tcl_GetStringFromObj (objPtr=0xec4dd0, lengthPtr=0x7ffffdfc40a4)
at /home/sehmann/tcl8.5.9/unix/../generic/tclObj.c:1629
#2 0x00007ffff7e73d47 in UpdateStringOfList (listPtr=0xec4dd0) at /home/sehmann/tcl8.5.9/unix/../generic/tclListObj.c:1872
#3 0x00007ffff7e82da6 in Tcl_GetStringFromObj (objPtr=0xec4dd0, lengthPtr=0x7ffffdfc41a4)
at /home/sehmann/tcl8.5.9/unix/../generic/tclObj.c:1629
#4 0x00007ffff7e73d47 in UpdateStringOfList (listPtr=0xec4dd0) at /home/sehmann/tcl8.5.9/unix/../generic/tclListObj.c:1872
#5 0x00007ffff7e82da6 in Tcl_GetStringFromObj (objPtr=0xec4dd0, lengthPtr=0x7ffffdfc42a4)
at /home/sehmann/tcl8.5.9/unix/../generic/tclObj.c:1629
#6 0x00007ffff7e73d47 in UpdateStringOfList (listPtr=0xec4dd0) at /home/sehmann/tcl8.5.9/unix/../generic/tclListObj.c:1872
#7 0x00007ffff7e82da6 in Tcl_GetStringFromObj (objPtr=0xec4dd0, lengthPtr=0x7ffffdfc43a4)
at /home/sehmann/tcl8.5.9/unix/../generic/tclObj.c:1629
#8 0x00007ffff7e73d47 in UpdateStringOfList (listPtr=0xec4dd0) at /home/sehmann/tcl8.5.9/unix/../generic/tclListObj.c:1872
#9 0x00007ffff7e82da6 in Tcl_GetStringFromObj (objPtr=0xec4dd0, lengthPtr=0x7ffffdfc44a4)
at /home/sehmann/tcl8.5.9/unix/../generic/tclObj.c:1629
#10 0x00007ffff7e73d47 in UpdateStringOfList (listPtr=0xec4dd0) at /home/sehmann/tcl8.5.9/unix/../generic/tclListObj.c:1872
#11 0x00007ffff7e82da6 in Tcl_GetStringFromObj (objPtr=0xec4dd0, lengthPtr=0x7ffffdfc45a4)
at /home/sehmann/tcl8.5.9/unix/../generic/tclObj.c:1629
#12 0x00007ffff7e73d47 in UpdateStringOfList (listPtr=0xec4dd0) at /home/sehmann/tcl8.5.9/unix/../generic/tclListObj.c:1872
#13 0x00007ffff7e82da6 in Tcl_GetStringFromObj (objPtr=0xec4dd0, lengthPtr=0x7ffffdfc46a4)
at /home/sehmann/tcl8.5.9/unix/../generic/tclObj.c:1629
#14 0x00007ffff7e73d47 in UpdateStringOfList (listPtr=0xec4dd0) at /home/sehmann/tcl8.5.9/unix/../generic/tclListObj.c:1872
#15 0x00007ffff7e82da6 in Tcl_GetStringFromObj (objPtr=0xec4dd0, lengthPtr=0x7ffffdfc47a4)
at /home/sehmann/tcl8.5.9/unix/../generic/tclObj.c:1629
#16 0x00007ffff7e73d47 in UpdateStringOfList (listPtr=0xec4dd0) at /home/sehmann/tcl8.5.9/unix/../generic/tclListObj.c:1872
#17 0x00007ffff7e82da6 in Tcl_GetStringFromObj (objPtr=0xec4dd0, lengthPtr=0x7ffffdfc48a4)
at /home/sehmann/tcl8.5.9/unix/../generic/tclObj.c:1629
#18 0x00007ffff7e73d47 in UpdateStringOfList (listPtr=0xec4dd0) at /home/sehmann/tcl8.5.9/unix/../generic/tclListObj.c:1872
#19 0x00007ffff7e82da6 in Tcl_GetStringFromObj (objPtr=0xec4dd0, lengthPtr=0x7ffffdfc49a4)
at /home/sehmann/tcl8.5.9/unix/../generic/tclObj.c:1629
There is a is pilot error: the elements in objv should have a reference count maintained by the caller. Do
for (i=0; i<3; i++) {
Tcl_IncrRefCount(cmdArgs[i]);
}
Tcl_EvalObjv((interp, 3, cmdArgs, TCL_EVAL_GLOBAL);
for (i=0; i<3; i++) {
result = Tcl_DecrRefCount(cmdArgs[i]);
}
Does this fix the problem?
Oops ... this box is bad for editing, isn't it? Make it
or (i=0; i<3; i++) {
Tcl_IncrRefCount(cmdArgs[i]);
}
result = Tcl_EvalObjv((interp, 3, cmdArgs, TCL_EVAL_GLOBAL);
for (i=0; i<3; i++) {
Tcl_DecrRefCount(cmdArgs[i]);
}
This works, thanks Miguel!
I can see if any Tcl internals do:
incr
do something
decr
then the object will get deleted so I need to incr/decr to make sure it survives to the end of the call. Is there any document describing this? All the tcl docs I have looked at so far have not highlighted this sort of point.
The man page http://tcl.tk/man/tcl8.5/TclLib/Eval.htm says: "The caller of Tcl_EvalObjv has to manage the reference count of the elements of objv, insuring that the objects are valid until Tcl_EvalObjv returns."
Conceded, the point was not stressed in the 8.4 man page.