0

我试图理解 Tcl 中的错误和异常。我写了一个小代码如下

proc Div3 {a b} {
    return [Div2 $a $b]
}

proc Div2 {a b} {
    return [Div $a $b]
}

proc Div {a b} {
   if {$b == 0} {
      error "Error generated by error" "Info String for error" 401
   } else {
      return [expr $a/$b]
   }
}

if {[catch {puts "Result = [Div3 10 0]"} errmsg]} {
   puts "ErrorMsg: $errmsg"
   puts "ErrorCode: $errorCode"
   puts "ErrorInfo:\n$errorInfo\n"
}

当我使用 运行它时tclsh.exe,调试器输出如下所示,

% tclsh error-file-1.tcl
ErrorMsg: Error generated by error
ErrorCode: 401
ErrorInfo:
Info String for error
    (procedure "Div" line 1)
    invoked from within
"Div $a $b"
    (procedure "Div2" line 2)
    invoked from within
"Div2 $a $b"
    (procedure "Div3" line 2)
    invoked from within
"Div3 10 0"

但是,当我使用tclsh.exe通过Komodo IDE运行相同的程序时,我得到的调试器输出如下

ErrorMsg: Error generated by error
ErrorCode: 401
ErrorInfo:
Info String for error
    invoked from within
"DbgNub_uplevelCmd 1 $cmd"
    invoked from within
"Div $a $b"
    invoked from within
"DbgNub_uplevelCmd 1 $cmd"
    invoked from within
"Div2 $a $b"
    invoked from within
"DbgNub_uplevelCmd 1 $cmd"
    invoked from within
"Div3 10 0"
    invoked from within
"DbgNub_uplevelCmd 1 $cmd"
    invoked from within
"DbgNub_Do 0 {1 17 {249 27}} {puts "Result = [DbgNub_Do 1 {1 17 {265 9}} {Div3 10 0}]"}"

我可以理解来自 Komodo IDE 的调试器输出,tclsh.exe但无法解释来自Komodo IDE的调试器输出。

特别是,我无法理解DbgNub_Do 0 {1 17 {249 27}} {puts "Result = [DbgNub_Do 1 {1 17 {265 9}} {Div3 10 0}]"}列表中显示的数字(即{1 17 {249 27}}DbgNub_uplevelCmd 1 $cmdDbgNub_Do

提前致谢

4

1 回答 1

1

堆栈跟踪中提到的所有DbgNub_命令都是 Komodo 的额外调试工具(将它们隐藏在堆栈跟踪中理论上是可能的,但很混乱,并且工具显然并没有真正做到这一点)。通常,您可能会忽略这些命令,因为部署时它们不会出现。

如果我们忽略这些DbgNub_uplevelCmd位,我们会得到:

Info String for error
    invoked from within
"Div $a $b"
    invoked from within
"Div2 $a $b"
    invoked from within
"Div3 10 0"
    invoked from within
"DbgNub_Do 0 {1 17 {249 27}} {puts "Result = [DbgNub_Do 1 {1 17 {265 9}} {Div3 10 0}]"}"

除了缺少行号信息(和DbgNub_Do,这显然是catch直接在内部检测代码)之外,这与标准跟踪明显相似。


通常,Tcl 的结果状态包括:

  1. 结果代码。这是TCL_OK(= 0)一段代码成功,TCL_ERROR(= 1)如果抛出异常,以及其他一些其他值(TCL_RETURNTCL_BREAKTCL_CONTINUE。这些名称是在 C 级别定义的。
  2. 存储在解释器中的结果值。在 Tcl 的古代版本中,这是一个简单的字符串,但 20 多年来它一直是一个引用计数的类型值。(Tcl 确实有一个类型系统。它与所有其他语言的不同之处在于字符串是所有其他类型的超类型。)
  3. 包含附加信息的结果字典。其中的标准条目(也可以定义您自己的)是:
    1. 错误信息,也就是被写入errorInfo全局以支持旧代码的堆栈跟踪。只有对错误才真正有意义。
    2. 错误代码,一种机器可读的异常描述符,它被写入errorCode全局以支持旧代码。同样,只有对错误才真正有意义。
    3. 错误行。用于在消息等中生成数字的位(procedure "Div" line 1)
    4. 级别,用于return进行多级返回。

还有一些其他零碎的东西只在少数情况下起作用(例如,当异常主体抛出时,当 atryfinally子句抛出异常时,在许多语言中都是一个棘手的情况)。

于 2020-03-23T15:23:51.270 回答