\errorcontextlines 有什么作用?

\errorcontextlines 有什么作用?

rotating包示例中,文档类之前包含一个命令。

\errorcontextlines32
\documentclass[twoside]{report}

当我应用\meaning\errorcontextlines它时,它没有显示任何定义。它有什么用处?

答案1

\errorcontextlines指 TeX 发现错误时输出的行数,这些行应该为用户提供一些有关错误发生原因的背景信息。

摘自 TeX Book(第 34 页):

如果您使用其他人设计的 TeX 格式包,您的错误消息可能会涉及许多难以捉摸的两行级别的宏上下文。通过\errorcontextlines=0在文件开头设置,您可以减少报告的信息量;TeX 将只显示顶部和底部的上下文行对以及最多 \errorcontextlines两行附加项目。(如果因此省略了任何内容,您还会看到“ ...”。)即使大部分大型上下文都被抑制,您也很有可能发现错误来源;如果没有,您可以说“ I\errorcontextlines=100\oops”并重试。(这通常会给您一个未定义的控制序列错误和大量上下文。)纯 TeX 设置\errorcontextlines=5

在上面的讨论中假设\oops未定义。

答案2

这个答案展示了如何使用\errorcontextlines/如何解释结果上下文,以及为什么该功能有用以及何时该功能无用以及您可以做什么。

也可以看看:编译 - 如何有效地追踪 LaTeX 错误? - TeX - LaTeX Stack Exchange


TeX 没有调用堆栈,但是这是宏扩展语言中最接近的。

如何使用此功能

考虑这个程序(带有适当的序言

\errorcontextlines=10000
\def\c{1 \errorerror 2}
\def\b #1 {7 #1 8}
\def\a{5 \b {3 \c 4} 6}
7 \a 8

相关输出是

! Undefined control sequence.
\c ->1 \errorerror 
                   2
<argument> 3 \c 
                4
\b #1 ->7 #1
             8
\a ->5 \b {3 \c 4} 
                   6
l.7 7 \a
         8

(然后 TeX 进入提示符(该行以 开头?)。)

错误信息的含义:

  • 某个文件第 7 行的内容查看此文件以了解它是哪个文件7 \a 8,而 TeX 刚刚读取了\a(3)
  • \a扩展为5 \b {3 \c 4} 6
  • \b扩展为7 #1 8
  • #1“扩展”为3 \c 4。 (实际上更像是“#1具有的值”)
  • \c扩展为1 \errorerror 2
  • 7 {expands \a} 5 {expands \b {3 \c 4}} 7 3 {expands \c} 1 \errorerror执行(3)之后,发生错误,2 4 8 6 8接下来将执行。

通常,底线就是代码中的位置。

与查找错误一样,大多数时候您要查找的地方是包含代码的最顶层. (例如,如果ac是库/包函数,并且\b是您的函数,您可能想要修改的定义\b

限制

扫描参数时出错

在这种情况下,TeX 将无法正确报告行号。请参阅 LaTeX 调试策略和括号不匹配更多细节。

未显示宏的行号

这个问题无法解决(除非重新编译 TeX/以某种方式修改执行),TeX 不会存储宏的定义位置。

线太短

...要查看行首/行末的内容,请参阅这个答案

缺少中间上下文行

引擎执行明确的“尾部调用优化”以避免在循环中建立内存,因此如果某个命令(加上它的参数)位于其他命令的末尾,那么它将在上下文中隐藏。

除了重新编译 TeX 之外,没有其他方法可以禁用此功能。(与 C 相比,编译器可以执行尾部递归,但在调试模式下不能执行此操作)

例如,如果代码修改为

\errorcontextlines=10000
\def\c{1 \errorerror}
\def\b#1{7 #1}
\def\a{5 \b{3 \c}}

7 \a 8
\def\a#1{1 #1}
\a{3 4 \errorerror 5 6}

错误信息将只是

\c ->1 \errorerror

l.13 7 \a
        8

所有中间错误上下文行均缺失。

尽管如此,在这种情况下你知道原因是尾部调用优化,无需重新编译 TeX,您可以查看宏的定义(\showlatexdef)来找出缺失的宏(它始终是最后一个。对于除“宏”之外的上下文行类型,这有点困难,但对于<argument>类型有\tracingmacros)。

这种行为导致问题很难调试的例子:参见问题

缺少底部上下文行

还有一种情况是你无法获取代码的最顶层:\usepackage

请参阅链接的评论为什么这个错误信息行号是错误的? - TeX - LaTeX Stack Exchange

要寻求解决方法,请参见下面的评论。

错误的令牌列表?

(3): 实际上,\a(第一行中的最后一个标记)是 TeX 最后“读取”的内容,不一定是当前正在扩展的内容。

此外,如果上下文来自文件,TeX 将显示行内容,而不是实际的待处理的下一个标记。如果上下文来自宏,TeX 将显示宏定义(即使 TeX 有能力从解析的标记列表中“重建”代码)

某些操作可能会让 TeX 读取一些更多的命令,包含错误定义的命令不是第一行最后一个命令。

例如:

\def\a{1 \errorerror 2}

7 \expandafter \a \a 8

错误信息:

\a ->1 \errorerror
                   2
\a ->
     1 \errorerror 2
l.12 7 \expandafter \a \a
                        8

注意:

  • 该错误是由于扩展第一的 \a宏观,而不是第二个,
  • 第二个\a以未展开的形式出现,而不是以曾经展开的形式出现。

缺少箭头 ( ->) / 参数

这是一个相对简单的问题,但请注意,如果宏体太长,箭头->可能会被省略。

./a.tex:11: Undefined control sequence.
\aaaaaaaaaaaaaaaaaaaa ...lax \relax \relax \ERROR 
                                                  \relax \relax \relax \rela...

l.11 \aaaaaaaaaaaaaaaaaaaa

在这种情况下,仍然应该理解宏名称是\aaaaaaaaaaaaaaaaaaaa,并且它可能有一些参数等。请参阅下面的代码。

\documentclass{article}
\errorcontextlines=100
\def\aaaaaaaaaaaaaaaaaaaa #1#2#3{
\relax \relax \relax \relax \relax \relax \relax \relax \relax \relax
\ERROR
\relax \relax \relax \relax \relax \relax \relax \relax \relax \relax
}
\aaaaaaaaaaaaaaaaaaaa {} {} {}

丢失的\

这也可能发生。代码

\escapechar=-1
\def\aaaaaaaaaaaaaaaaaaaa #1#2#3{
\relax \relax \relax \relax \relax \relax \relax \relax \relax \relax
\ERROR
\relax \relax \relax \relax \relax \relax \relax \relax \relax \relax
}
\aaaaaaaaaaaaaaaaaaaa {} {} {}

创建与上面类似的消息,但是没有 \s

./a.tex:12: Undefined control sequence.
aaaaaaaaaaaaaaaaaaaa ...x relax relax relax ERROR 
                                                  relax relax relax relax re...

l.12 \aaaaaaaaaaaaaaaaaaaa {} {} {}

标记列表来源的宏名称错误

这有时会发生在 expl3 代码或类似代码的“回调”中。

例如

\cs_new_protected:Npn \mymacro {
    \peek_analysis_map_inline:n {ab \error cd}
}
\mymacro 1

那么回溯将具有以下形式

\__tl_analysis_map_1:nnN #1#2#3->\group_end: ab\error 
                                                      cd\__tl_peek_analysis_loop:NNn \prg_break_point:Nn \peek_analysis_map_break: {}
l.9 \mymacro 1

而不是你所期望的,那就是

\mymacro->\peek_analysis_map_inline:n {ab \error
                                                 cd}
l.9 \mymacro 1

尽管错误的标记\error最初来自\mymacro,但回溯显示它来自\__tl_analysis_map_1:nnN
因为内部参数 {\peek_analysis_map_inline:n {ab \error cd}}存储在该宏中,然后从那里执行)。

类似的情况也发生在简单的条件下,例如

\cs_new_protected:Npn \mymacro {
    \bool_if:NT \c_true_bool {
        ab \error cd
    }
}
\mymacro

这给出了回溯

<argument> ab\error 
         cd
\use:n #1->#1
             
l.11 \mymacro

缩进错误

由于某种原因,如果第一个例子是用 LuaLaTeX 而不是 PDFLaTeX 编译的,下面这一行的缩进<argument>将是错误的:

! Undefined control sequence.
\c ->1 \errorerror 
                   2
<argument> 3 \c 
     4
\b #1 ->7 #1
             8
\a ->5 \b {3 \c 4} 
                   6
l.7 7 \a
       8

幸运的是,这个问题不是很严重,仍然可以分辨出哪条线是哪条。

输出中的 CR/LF 字符

通常会有 2 行,但有时可能会有更多,因为标记列表本身包含一些 CR/LF 字符。

我不知道如何解决这个问题。

边注

相关内容