2

有时您无法理解变量值何时更改。并且有必要通过在变量上放置一个观察点来找到该行。如何做到这一点?TCL trace 命令可以用来获取修改变量的行吗?

4

1 回答 1

4

要将观察点放在变量上,请使用trace命令。您可以通过命令获取有关分配变量的上下文的扩展信息info,尤其是levelframe子命令。(后者仅从 Tcl 8.5 开始可用。)

像这样把东西放在一起应该可以提供你想要的信息:

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

但它并不完全有效。您可以轻松找到更新变量时正在运行的过程,但是在该过程中发生更新的位置仍然遥不可及。(相反,您会看到跟踪回调本身的调用,或者在堆栈的上一层,对执行操作的过程的调用,这两者都没有用...)


[编辑]:另一种方法是假设哪个命令正在执行更新(例如,set)并做一些 jiggery-pokery 以便info level(唯一可以提供行号的命令)可以做正确的事情:

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]
}

这样可行。将它扩展到其他设置变量的命令(例如,[incr]、[lappend]、[lset])也相当容易。一个更高级的探针是这样的:

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<)"
            }
        }
    }
}

随意尝试!

于 2011-04-24T16:05:24.987 回答