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

发布于 2024-11-02 19:44:21 字数 77 浏览 4 评论 0原文

有时您无法理解变量值何时更改。并且有必要通过在变量上放置观察点来找到这条线。如何做到这一点? TCL 跟踪命令对于获取变量被修改的行有用吗?

Sometimes you can't understand when the variable 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

不爱素颜 2024-11-09 19:44:21

要在变量上放置观察点,请使用 trace< /code>命令。您可以通过 获取有关分配变量的上下文的扩展信息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)并进行一些调整,以便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<)"
            }
        }
    }
}

随意尝试!

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!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文