【问题标题】:Tcl program whose behavior changes depending on a "puts" statementTcl 程序的行为根据“puts”语句而改变
【发布时间】:2012-09-28 14:57:56
【问题描述】:

主要问题:

puts 语句(尽管是硬编码字符串)如何影响程序流程?


我将直接研究不完整的代码片段,原因将在后面解释。

proc bgerror { error } {
    puts "Background error: $error"
    exit 1
}

运行我的 Tcl 程序,我得到:

Background error: can't read "YPE(PROCESS)": no such variable

很公平,我想;一定是在某处搞砸了$ 或括号。为了找到问题,我将puts 语句放在各处并重新运行程序。

然而这一次,我的程序崩溃了:

9526:   tclsh testProgram
 fffffd7ffeafebba waitid   (0, 253d, fffffd7fffdf4950, 3)
 fffffd7ffeaeff9d waitpid () + 7d
 fffffd7ffe635132 __1cPGetPstackOutput6Fiiipci_v_ () + b2
 fffffd7ffe634bfb App_CoreSignalHandler () + 76b
 fffffd7ffeafb7b6 __sighndlr () + 6
 fffffd7ffeaf0b82 call_user_handler () + 252
 fffffd7ffeaf0d68 sigacthandler (b, fffffd7fffdfa500, fffffd7fffdfa1a0) + a8
 --- called from signal handler with signal 11 (SIGSEGV) ---

哎哟。

最后,我发现了一件非常奇怪的事情:

proc OnNewState { } {
    puts "foobar"
    # ...
}

使用 puts 声明,我得到了崩溃。 没有它,我得到原来的错误。 (嗯?!)我来回翻了很多次,以确保它是确定性的——确实如此。

现在,我一头扎进不完整的代码片段的原因是我想把注意力集中在抽象上,而不是细节上。

(完整的代码复杂且不透明,主要利用我公司的基础设施库,因此无论如何简化它以使其易于理解是不切实际的。此外,我已经知道问题源于基础设施库之一,因为当我删除一些与 TCP 发布者/订阅者堆栈库相关联的代码时,问题就消失了。)

puts 语句(尽管是硬编码字符串)如何影响程序流程?

即使我开始深入研究相关库的 C 源代码,我也不知道要查找什么。

希望有经验的 Tcl'ers 能有所启发...

【问题讨论】:

  • 我能想到的一件事是puts 与解释器的“结果对象”混淆了。理论上,如果您的 Tcl 库以某种方式不正确地访问它,这将解释崩溃。在任何情况下,我都会尝试生成 Tcl 运行时的适当回溯,并尝试在 comp.lang.tcl 上获得帮助。

标签: debugging crash tcl puts


【解决方案1】:

首先,您提供的证据告诉我们,您在使用 SIGSEGV 处理程序的上下文中,并且它是由自定义代码设置的(Tcl 没有设置 SIGSEGV 处理程序)。

Tcl 的puts 命令只会通过生成错误来影响控制流,并且如果您传递错误数量的参数、无效参数或在 I/O 层遇到问题(例如,如果你关闭了stdout 频道)。一个简单的puts "foobar" 绝对是一个有效的调用,所以问题出在通道层。或者你有一个非标准的puts;如果您的自定义代码替换了标准版本,那么几乎任何事情都可能发生。

那么可能会发生什么?好吧,在这个阶段,我最初的怀疑是你的程序中的其他地方出现了内存损坏,并且这以某种方式影响了stdout 频道的内部。如果我是对的,你会发现很难找到这个。 非本地崩溃总是难以追踪。我建议您使用某种组合来关闭该信号处理程序,附加gdb 以便您可以看到崩溃真正 发生的位置,并使用valgrind 来确保正确处理内存(如果您'很幸运,valgrind 会直接指出问题所在)。

【讨论】:

  • 嗨,Donal,一如既往地感谢您提供的有用答案。最终我们解决了这个问题。我们的基础设施小组小心翼翼地不要弄乱 Tcl 的内部结构(因为担心意外后果),并且我们所有的包和过程名称都以 Fid_ 为前缀,所以我怀疑 puts 是否被覆盖。所以它一定是内存损坏。在代码中的某个时刻,发出了一个命令来“联系”另一个服务。然而,后来发现在代码中,另一个命令也在内部联系该服务,显然两次联系服务是一个禁忌。没有调查原因,但有一天......
猜你喜欢
  • 2011-11-11
  • 1970-01-01
  • 1970-01-01
  • 2021-04-10
  • 2015-07-27
  • 1970-01-01
  • 1970-01-01
  • 2019-04-01
  • 1970-01-01
相关资源
最近更新 更多