- priority: 5 --> 7
- assigned_to: nobody --> ghowlett
Hi,
I am a big fan of BLT and I've been using it for a Waveform Viewer I've written in TCL/TK.
I recently decided to write a tcl profiler for another application to gather statistics (on number of function calls, their callers, and their runtime) and i've found out about blt::watch. I've found and fixed a bug that i am now reporting here.
Cheers
Ersin Beyret
At bltWatch.c, at PreCmdProc, Watch::cmdPtr is initialized as:
watchPtr->cmdPtr = command
cmdPtr is later on referered from PostCmdProc. However it looks like by the time that reference happens, the memory it points to changes.
Here is a script to replicate the behavior:
proc preCmd { level command argv } {
puts "PRE :> [string repeat - $level] $command | $argv <: PRE"
}
proc postCmd { level command argv retcode results } {
puts "POST:> [string repeat - $level] $command | $argv | $retcode | $results :<POST"
}
blt::watch create trace -postcmd postCmd -precmd preCmd
set myvar myvalue
======================================================
Run it as 'bltsh example_cmdptr.tcl'
It is supposed to print this as output:
PRE :> - set myvar myvalue
| set myvar myvalue <: PRE
POST:> - set myvar myvalue
| set myvar myvalue | OK | myvalue :<POST
However, due to the bug, the first part of 'POST' line won't come out as expected.
Here is how i've fixed it:
1) At PreCmdProc:
// Ersin 02/15/08. Similar to 'args', cmdPtr needs to be alloc'ed
//watchPtr->cmdPtr = command;
if (watchPtr->cmdPtr != NULL) {
Blt_Free(watchPtr->cmdPtr);
}
watchPtr->cmdPtr = Blt_Strdup(command);
2) At PostCmdProc, right after 'args' is freed:
Blt_Free(watchPtr->cmdPtr);
watchPtr->cmdPtr = NULL;
3) At DestroyWatch, right after 'args' is freed:
if (watchPtr->cmdPtr != NULL) {
Blt_Free(watchPtr->cmdPtr);
}
diff -c output is below (line #s may be different depending on the version of the original file)
*** 149,161 ****
if (watchPtr->active) {
return; /* Don't re-enter from Tcl_Eval below */
}
! // Ersin 02/15/08. Similar to 'args', cmdPtr needs to be alloced
! //watchPtr->cmdPtr = command;
! if (watchPtr->cmdPtr != NULL) {
! Blt_Free(watchPtr->cmdPtr);
! }
! watchPtr->cmdPtr = Blt_Strdup(command);
watchPtr->level = level;
--- 147,153 ----
if (watchPtr->active) {
return; /* Don't re-enter from Tcl_Eval below */
}
! watchPtr->cmdPtr = command;
watchPtr->level = level;
*** 298,306 ****
Blt_Free(watchPtr->args);
watchPtr->args = NULL;
- Blt_Free(watchPtr->cmdPtr);
- watchPtr->cmdPtr = NULL;
-
--- 287,292 ----
*** 419,427 ****
if (watchPtr->args != NULL) {
Blt_Free(watchPtr->args);
}
- if (watchPtr->cmdPtr != NULL) {
- Blt_Free(watchPtr->cmdPtr);
- }
--- 404,409 ----