LaTeX 的故障分两种:一种会明明白白打出以 ! 开头的行,另一种一声不吭地坏掉。费时间的往往是后者——编译多少次都停在 ?? 的交叉引用、落到两页之后的插图、源文件明明写着 letterpaper 却输出 A4 的 PDF、在自己机器上能编译却唯独在合作者那里失败的稿件。这个常见问题页只收集那些横跨多个机制的问题,并从「运行过程中究竟发生了什么」来回答。凡是一条错误信息就能定案的问题,都有各自的专页,可从文末的索引进入。
为什么必须编译两次
因为 LaTeX 从头到尾只读一遍源文件,无法预知后文。排到第 1 页的 \ref{sec:first} 时,对应 \label 最终会是几号还没确定。于是 \label 把编号写进 .aux 文件,而 \ref 读的是上一次运行留下的 .aux。在 TeX Live 2024 上实测:第一遍会打印 LaTeX Warning: Reference 'sec:first' on page 1 undefined on input line 4. 与 LaTeX Warning: There were undefined references.,PDF 上确实印着「See Section ?? on page ??.」。此时 .aux 中已写入 \newlabel{sec:first}{{1}{1}{}{}{}},第二遍读到它,就变成「See Section 1 on page 1.」。所以 ?? 不是坏了,而是在告诉你还在第一圈。
$ pdflatex ref.tex # run 1
LaTeX Warning: Reference 'sec:first' on page 1 undefined on input line 4.
LaTeX Warning: There were undefined references.
LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.
$ pdftotext ref.pdf -
See Section ?? on page ??.
$ pdflatex ref.tex # run 2 — no warnings
$ pdftotext ref.pdf -
See Section 1 on page 1.运行末尾那条 LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.,是 LaTeX 在报告:刚写出的 .aux 与读进来的那份不一致,请再跑一遍。要点在于两遍是下限而不是定则。多出一位数字就可能让一行重排,页码随之改变,.aux 又变了;一旦牵扯目录、图表目录或 hyperref 书签,跑三遍四遍完全正常。latexmk 的存在意义正在于此:反复运行直到 .aux 不再变化。所以别再用手数遍数,交给它迭代。反过来说,看到 ?? 时先编译两遍再怀疑别的。若两遍之后仍在,那就是 \label 拼错、根本没写 \label,或者旧的 .aux 挡了路——删掉 .aux 就回到第一遍。
参考文献列表不出现、引用停在 [?]
因为文献处理由 LaTeX 之外的另一个程序负责,而且走完一圈需要四条命令。bibtex 根本不读 .tex,它读的是 LaTeX 写进 .aux 的 \citation 与 \bibdata,再从 .bib 中取出对应条目生成 .bbl。在 TeX Live 2024 上实测,三个阶段泾渭分明。第一次 pdflatex 打印 LaTeX Warning: Citation 'knuth1984' on page 1 undefined,PDF 上是「As shown by [?].」,参考文献列表连影子都没有。运行 bibtex 会报告读入来源:The top-level auxiliary file: doc.aux、The style file: plain.bst、Database file #1: refs.bib。第二次 pdflatex 确实排出了 References 列表,但正文里的引用仍是 [?]。直到第三次才变成 [1]。
pdflatex doc # writes \citation and \bibdata into doc.aux; text shows [?]
bibtex doc # reads doc.aux + refs.bib, writes doc.bbl
pdflatex doc # pulls in doc.bbl: the list appears, the mark is still [?]
pdflatex doc # now the \bibitem labels are in doc.aux: the mark becomes [1]
latexmk -pdf doc # does all four, and repeats until nothing changes需要第三遍,同样由 .aux 的往返决定。第二遍读入的 .bbl 里,\bibitem 会把「这个键对应 [1]」的映射写进 .aux——但那是在同一次运行的中途,此时正文里的 \cite 早已排好。于是这份映射只能从下一次运行起生效,所以需要第三次 pdflatex,也就是总共第四条命令。biblatex 加 biber 的形状完全一样,只是 biber 取代 bibtex 并读取 .bcf。实务上交给 latexmk,就不必再数遍数。若列表仍是空的,原因几乎总是三者之一:\bibliography{refs} 误写成带 .bib 扩展名、正文里一个 \cite 都没有(加 \nocite{*} 可列出全部)、键拼错了。最后一种会在 .blg 日志里显示 Warning--I didn't find a database entry for "..."。
插图不在预期位置、跑到别的页去了
因为 figure 是浮动体:LaTeX 会一直扣着它,直到某一页腾出位置。多数人栽跟头的地方,是 \newpage 与 \clearpage 的区别。\newpage 只是「就此结束当前页」,并不排出正在等待的浮动体;\clearpage 则先把所有待处理的浮动体输出,再结束该页。用同一份源文件,仅把这一条命令互换,在 TeX Live 2024 上分别编译,再用 pdftotext 逐页查看内容,差别一目了然。
\section{Alpha}
... a page of text ...
\begin{figure}[t]
\centering \rule{10cm}{16cm}
\caption{First figure}
\end{figure}
\newpage % <- only this line differs between the two builds
%\clearpage
\section{Beta}
\begin{figure}[t]
\centering \rule{6cm}{5cm}
\caption{Second figure}
\end{figure}
Text of Beta.\newpage 版共 4 页:p.1 是 Alpha 的正文,p.2 是「Beta」标题及其正文,p.3 是图 1,p.4 是图 2。属于 Alpha 节的图 1 越过了下一节的标题,跑到它后面去了。\clearpage 版只有 3 页:p.1 是 Alpha 的正文,p.2 只有图 1,p.3 是图 2 加「Beta」标题及正文。图不再跨越节的边界,篇幅也少了一页。所以「插图跑进了别的章」多半源于在结构断点处用了 \newpage。章节断点请用 \clearpage(双面印刷用 \cleardoublepage)。此外,位置参数应写 [htbp] 而不是孤零零的 [h]——[h] 的含义是「放得下就放这里,否则押后」,而高度超过 \textheight 的浮动体永远无法与正文同页。浮动体的精细控制由「浮动体与配置」页负责。
图片完全不显示、或只剩一个空框
若是「什么都没出来」,先怀疑图片格式与输出路线不匹配;若是「只剩一个空框」,先怀疑 draft。pdflatex 能直接读的是 PDF、PNG、JPEG,完全读不了 EPS——请用 epstopdf 转换,或交给 epstopdf 宏包。而 platex → dvipdfmx 的 DVI 路线可以处理 EPS。找不到文件时的信息是 ! LaTeX Error: File 'fig.eps' not found.,原因几乎总是漏写扩展名、路径写错,或 \graphicspath{{figures/}} 少了结尾的斜杠。另一条经典信息 ! LaTeX Error: Cannot determine size of graphic in xxx.png (no BoundingBox).,出现在没有把驱动选项告知 graphicx 的时候——Cloud LaTeX 自家的 FAQ 也把这一条单列为一个条目。
至于「只剩一个空框」,弄清原因后简单得让人泄气。用 \documentclass[draft]{article} 载入图片,在 TeX Live 2024 上编译后再用 pdftotext 查看,本该是图的位置出现的是文件名的文本。draft 的作用正是如此:跳过图像绘制,只留下同样尺寸的框和文件名。忘了自己在类选项里写过 draft,转而怀疑图片损坏,是 LaTeX 中最常见的事故之一。提交版务必去掉 draft;若只是想提速,可以用 \usepackage[draft]{graphicx} 把影响限制在图形上。另外,若本节列出的原因都排除后图仍不见,那也许它并非「没出来」,而是「浮到别的页去了」——请回到上一节。
在我这里能编译,在合作者那里却失败
两台机器的差异,实际上可归结为三点:TeX Live 的年份、已装宏包的版本,以及放在个人目录树里的自制文件。前两点只需加一行即可可视化。在 \documentclass 之前写上 \listfiles 再编译,.log 末尾就会输出 *File List* 区块,每个文件一行,带日期与版本——在 TeX Live 2024 上是 amsmath.sty 2023/05/13 v2.17o AMS math features、graphicx.sty 2021/09/16 v1.2d Enhanced LaTeX Graphics 这样的条目。让合作者也发来同一段,做个 diff,元凶往往就在某一行上。引擎自身的年份则由 pdflatex --version 给出:pdfTeX 3.141592653-2.6-1.40.26 (TeX Live 2024)。
% put this on the very first line of the source
\listfiles
$ pdflatex doc.tex && sed -n '/File List/,/^ \*\*\*/p' doc.log
*File List*
article.cls 2023/05/17 v1.4n Standard LaTeX document class
amsmath.sty 2023/05/13 v2.17o AMS math features
graphicx.sty 2021/09/16 v1.2d Enhanced LaTeX Graphics (DPC,SPQR)
$ kpsewhich -var-value=TEXMFHOME # macOS, TeX Live 2024
/Users/you/Library/texmf
$ pdflatex --version | head -1
pdfTeX 3.141592653-2.6-1.40.26 (TeX Live 2024)第三项「个人目录树」最难察觉。在 macOS 的 TeX Live 2024 上执行 kpsewhich -var-value=TEXMFHOME,返回的是 /Users/你/Library/texmf(因为 TeX Live 2024 随附的 texmf.cnf 里写着 TEXMFHOME = ~/Library/texmf;Windows 与 Linux 的默认值则是 ~/texmf)。放在那里的 .sty、.bst 或自备字体只有你自己看得见,收到稿件的人会得到 ! LaTeX Error: File 'mystyle.sty' not found.。对策很直白:自制文件放进稿件文件夹,随稿一起交付。若还想连 TeX Live 年份差异一并抹平,用 Docker 镜像之类把环境本身固定下来最为稳妥。协作的做法由「共同写作与修订管理」页负责,环境固定则由「Docker / CI」页负责。
明明写了 letterpaper,PDF 却是 A4
因为类选项改变的是版面(正文尺寸与页边距),而不是 PDF 的纸张本身。在 TeX Live 2024 上直接编译 \documentclass[letterpaper]{article},再用 pdfinfo 查看,得到的是 Page size: 595.276 x 841.89 pts (A4)。原因在 pdfTeX 的启动配置:被固化进格式文件的 pdftexconfig.tex 设定了 \pdfpageheight = 297 true mm 与 \pdfpagewidth = 210 true mm,而这两者是决定 PDF 媒体框的原语,类选项够不到这一层。给同一份文档加上 \usepackage[letterpaper]{geometry},结果就变成 612 x 792 pts (letter)——因为 geometry 同时管版面和纸张尺寸。
$ pdflatex letter.tex && pdfinfo letter.pdf | grep "Page size"
Page size: 595.276 x 841.89 pts (A4) # \documentclass[letterpaper]{article}
# fix 1 — geometry sets the type area AND the sheet
% \usepackage[letterpaper]{geometry}
Page size: 612 x 792 pts (letter)
# fix 2 — set the pdfTeX primitives before \documentclass
% \pdfpagewidth=8.5truein \pdfpageheight=11truein
Page size: 612 x 792 pts (letter)对策有三种,视情况选用。最直白的是使用 geometry,还能把页边距一并写在同一处。若不想让导言区变长,在 \documentclass 之前写 \pdfpagewidth=8.5truein \pdfpageheight=11truein,同样得到 612 x 792 pts (letter)(已实测)。走 DVI 路线时,真正生成 PDF 的是 dvipdfmx,因此要在转换端指定,例如 dvipdfmx -p letter。顺带记住这里为何加 true:当用 \mag 整体缩放时,只有标了 true 的尺寸不受缩放影响。纸张相关的细节由「生成 PDF」页负责。
日文不显示或出现乱码
几乎必然是引擎或文字编码用错了。pdflatex 根本无法排日文。可行的路线有两条:uplatex(配 jsarticle 或 jlreq 类)交给 dvipdfmx,或者 lualatex 加 luatexja。源文件请保存为 UTF-8。容易被忽略的是,「支持日文」并非只有一种:platex 与 uplatex 能处理的字符范围不同。在 TeX Live 2024 上,把含「髙」(U+9AD9)的一行喂给 platex,会停在 ! LaTeX Error: Unicode character ^^e9^^ab^^99 (U+9AD9) not set up for use with LaTeX.,而 uplatex 编译同一行毫无警告。所以若文档只在人名或异体字处出错,该怀疑的是引擎而非字体。
若字确实出来了却是豆腐块(□)或换成了别的字体,那就是和文字体的设置问题。在 dvipdfmx 路线上,用 kanji-config-updmap 选择要嵌入的日文字体;在 LuaTeX-ja 下则用 \setmainjfont 之类指定。另外,若只有对方那边乱码,请怀疑编码与换行符——只要混入了非 UTF-8(Shift_JIS 或 EUC-JP)保存的文件,platex 就会依 -kanji= 的设定改变解读方式。日文排版方式本身由「日文排版方法」页负责,编码与换行则由「编码与换行」页负责。
被告知字体没有嵌入
要用 pdffonts 核实,而不是靠猜。对在 TeX Live 2024 上生成的普通 pdfLaTeX 输出运行它,会看到 emb、sub、uni 三列,某一行如 KJJYRX+CMR10 Type 1 Builtin yes yes yes——emb 为 yes,且字体名前带有六个字母的子集前缀。两点齐备即表示已嵌入。反之,只要有一行 emb 为 no,期刊投稿系统或 PDF/A 检查必定在那里卡住。典型原因有三:Type 3 位图字体(没有相应的 Type1,于是用了 METAFONT 位图)、PDF 标准十四种基本字体(引用 Helvetica 之类却不提供实体),以及 dvipdfmx 的映射指向了不可嵌入的字体。
$ pdffonts document.pdf
name type encoding emb sub uni object ID
-------------------------- ---------- --------- --- --- --- ---------
KJJYRX+CMR10 Type 1 Builtin yes yes yes 4 0
# "yes" under emb, plus the six-letter subset prefix, means embedded.
# Any line with "no" under emb will fail a PDF/A or journal check.哪一页回答哪一条错误信息
以上这些问题都没有共同的错误信息;但一旦出现以 ! 开头的行,情况就不同了:信息本身决定了去处。本站的 errors 区块按「一条信息一页」编排,! Missing $ inserted.、! Undefined control sequence.、! LaTeX Error: Missing \begin{document}.、Runaway argument?、! LaTeX Error: Option clash for package ...、Overfull \hbox 各有专页。下表给出在 TeX Live 2024 上实际复现时的原文,以及那一行究竟在说什么。阅读只有一个诀窍——先修最上面那条错误。TeX 的错误会连锁,下面的多半只是第一条的余震。
| 信息 | 通常的原因 |
|---|---|
! Missing $ inserted. | 在正文里用了 _、^ 等只能在数学模式中出现的记号 |
! Undefined control sequence. | 命令拼写错误,或者没有加载定义它的宏包 |
! LaTeX Error: Missing \begin{document}. | 导言区里有会被排印的内容——多半是误入的字符或 BOM |
Runaway argument? | } 忘了闭合,或参数中间出现空行;随后会打印 ! File ended while scanning use of ... |
! LaTeX Error: Option clash for package | 同一个宏包被用不同选项加载了两次——常常是文档类先加载过 |
Overfull \hbox | 某行无法断开而超出了版心;这是警告而非错误,PDF 仍会生成 |
LaTeX Warning: There were undefined references. | 还在第一圈;再编译一次即可——若仍不消失,问题在 \label 一侧 |