How to know what operator at which line changes the value of the variable in TCL
Sometimes you can't understand when the v开发者_运维知识库ariable value gets changed. And it is necessary to find the line by puting a watchpoint on the variable. How this can be done? Can TCL trace command be usefull in order to get the line where the variable was modified?
To put a watchpoint on a variable, you use the trace
command. You can get extended information about the context in which a variable was assigned through the info
command, notably the level
and frame
subcommands. (The latter is only available from Tcl 8.5 onwards.)
Putting things together like this should give the information you want:
trace add variable x write peekLocation
proc peekLocation args {
puts "WRITTEN FROM >[info level -1]< CALL"
puts "DETAILS: [info frame -1]"
}
# Demonstration...
proc foobar {} {
global x
set x "jibber jabber"
}
foobar
It doesn't quite work though; you can easily find what procedure was in operation at the time the variable was updated, but where in that procedure the update happened remains out of reach. (You instead see the invocation of the trace callback itself or, at one level further up the stack, the call to the procedure doing the manipulation, neither of which is that useful...)
[EDIT]: A different approach is to assume which command is doing the update (e.g., set
) and to do a bit of jiggery-pokery so that info level
(the only command that can provide a line number) can do the right thing:
rename set __orig_set;proc set args {doTrace;uplevel 1 [list __orig_set {*}$args]}
# Separate the probe from the instrumentation
proc doTrace {} {
puts [info frame -2]
}
That works. It's also fairly easy to extend it to other commands that do setting of variables (e.g., [incr], [lappend], [lset]). A fancier probe is this:
proc doTrace {} {
__orig_set f [info frame -2]
dict with f {
switch $type {
source {
puts "Write happened on line $line of file $file"
}
proc {
puts "Write happened on line $line of procedure $proc"
}
default {
puts "Write happened on line $line (command was >$cmd<)"
}
}
}
}
Feel free to experiment!
精彩评论