0

主要问题:

一个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能有所启发...

4

1 回答 1

3

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

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

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

于 2012-09-29T08:07:59.983 回答