如何知道哪一行的运算符改变了TCL中变量的值

时间:2011-04-24 09:57:23

标签: debugging tcl watchpoint

有时您无法理解变量值何时发生变化。并且有必要通过在变量上设置观察点来找到该行。怎么做到这一点? TCL跟踪命令可以用来获取修改变量的行吗?

1 个答案:

答案 0 :(得分: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<)"
            }
        }
    }
}

随意尝试!