【LaTeX】\protectでよくあるエラーと解決策!トラブルシューティング完全ガイド

2025-05-16

\protect の役割

LaTeXでは、コマンドやマクロは通常、すぐに展開(実行)されます。しかし、特定の状況下では、この「即時展開」が問題を引き起こすことがあります。代表的な例が、目次や見出し、キャプションなど、文書の補助的な部分にマクロを使用する場合です。

たとえば、章の見出しにカスタムマクロを使いたいとします。通常、LaTeXは章見出しのテキストを「目次」にも書き出します。このとき、もしその見出しに含まれるマクロが即座に展開されてしまうと、目次を生成する際に意図しない結果になったり、エラーになったりすることがあります。

\protectコマンドは、このような場面でマクロの展開を一時的に抑制し、「後で(目次などが生成される段階で)展開してほしい」という指示をLaTeXに与えるために使われます。これにより、LaTeXは目次などに記述する際に、そのマクロをそのままの形で保存し、実際に表示する段階になって初めて展開するようになります。

例として、章見出しにユーザー定義のコマンドを使いたい場合を考えます。

\documentclass{article}
\usepackage{japanese-babel} % 日本語を使用する場合

\newcommand{\mycommand}[1]{\emph{#1}} % カスタムコマンドを定義

\begin{document}

\tableofcontents % 目次を生成

\section{これは\mycommand{重要な}セクションです} % \protectなしの場合

\section{これは\protect\mycommand{重要な}セクションです} % \protectありの場合

\end{document}

この例で、

  • \section{これは\protect\mycommand{重要な}セクションです} の場合:

    • \protectがあることで、LaTeXは目次を作成する際に\mycommandをそのままの形で保存します。そして、実際に目次が表示される段階になって初めて\mycommandが展開され、正しく「重要な」が斜体で表示されるようになります。
  • \section{これは\mycommand{重要な}セクションです} の場合:

    • LaTeXは目次を作成する際に、\mycommandを即座に展開しようとします。しかし、目次を生成する段階では、\emphのような書式設定コマンドがうまく処理できないことがあります。結果として、目次に「重要な」という部分が斜体にならない、あるいはエラーが発生する可能性があります。


\protect 関連の一般的なエラーとトラブルシューティング

  1. 目次や見出しでマクロが正しく表示されない、またはエラーになる これは\protectの最も典型的な利用ケースであり、同時に最も一般的なトラブルの原因でもあります。

    • エラーの症状:

      • 目次や見出しの生成時にエラー(例: ! Missing control sequence inserted., ! Undefined control sequence. など)が発生する。
      • 目次や見出しに、意図した書式(例: 斜体、太字、色など)が適用されない。
      • 目次や見出しに、定義したマクロ名がそのまま表示されてしまう(例: \mycommand{テキスト})。
    • 原因: 目次などを生成する際、LaTeXは\writeコマンドを使って情報を.auxファイル(補助ファイル)に書き出します。このとき、マクロが\protectされていないと、\writeがマクロを即座に展開しようとし、上記のような問題が発生します。\writeのコンテキストでは、多くの書式設定コマンドやユーザー定義コマンドが正しく機能しないためです。

    • トラブルシューティング: この問題のほとんどは、問題のマクロの前に\protectを追加することで解決します。

      % 悪い例
      \section{これは\mycommand{重要な}セクションです}
      
      % 良い例
      \section{これは\protect\mycommand{重要な}セクションです}
      

      もし\mycommandが引数を持たないマクロであれば、\section{これは\protect\mycommand セクションです}のように、\mycommandの直前に\protectを置きます。

  2. \protectを付けたのに解決しない、あるいは別のエラーが出る \protectを正しく使っているはずなのに問題が解決しない場合、より複雑な原因が考えられます。

    • 原因1: \protected@edef または \protected@xdef の使用 一部のパッケージや、より高度なマクロ定義では、\protected@edef\protected@xdefのように、既に\protectされた展開を行う内部コマンドが使われていることがあります。これらのコマンドで展開されるマクロにさらに\protectを付け加えると、\protectが二重に適用され、かえって問題を引き起こすことがあります。

    • トラブルシューティング1: 定義しているマクロがどのように展開されるかを理解する必要があります。もし、自分で書いたマクロであれば、\protected@edef\protected@xdefを使っていないか確認します。他人のパッケージを使っている場合は、そのパッケージのドキュメントで、特定のコマンドに\protectが必要かどうか、あるいは不要かどうかの指示がないか確認します。 一般的には、\protectは「必要なところにだけ付ける」のが原則です。

    • 原因2: \protectの場所が正しくない \protectは、保護したいマクロの直前に置く必要があります。マクロの引数の中や、関係ない場所に置いてしまうと効果がありません。

    • トラブルシューティング2: \protectをどのコマンドの前に置くべきかを再確認します。通常、書式設定コマンドやユーザー定義コマンドなど、特定の文脈で展開されてしまうと困るコマンドの直前です。

    • 原因3: コマンドが「頑丈 (robust)」でない LaTeXには、\emph\textbfのように、元から\protectがなくても目次などで正しく機能する「頑丈な」コマンドと、そうでない「脆弱な (fragile)」コマンドがあります。ユーザーが定義するほとんどのコマンドは、デフォルトでは「脆弱」です。 特定のパッケージのコマンドが脆弱であるために\protectが必要なのに、それが忘れられている場合があります。また、自分で定義するマクロを最初から「頑丈」にしたい場合は、\DeclareRobustCommand を使うことができます。

      % 脆弱なマクロ(\protectが必要な場合がある)
      \newcommand{\myfragilecommand}{...}
      
      % 頑丈なマクロ(通常\protectは不要)
      \DeclareRobustCommand{\myrobustcommand}{...}
      
    • トラブルシューティング3: もし多くの場所で特定のコマンドに\protectを付けなければならない場合、そのコマンドを\DeclareRobustCommandで定義し直すことを検討してください。ただし、\DeclareRobustCommandは常に万能というわけではなく、複雑なマクロの場合には、やはり\protectを個別に使用する必要があることもあります。

  3. 無限ループやメモリ不足のエラー 非常に稀ですが、\protectの誤用や、複雑なマクロの相互作用によって、無限ループやメモリ不足を引き起こすことがあります。

    • エラーの症状:
      • LaTeXコンパイルが非常に遅くなる、または途中で止まる。
      • ! TeX capacity exceeded, sorry [main memory size=...]. のようなエラーメッセージが表示される。
    • 原因: これは通常、\protectの直接的な原因というよりは、マクロの再帰的な定義や、展開順序の誤りが根本にあり、\protectがその症状を悪化させる形で現れることが多いです。たとえば、\protectがマクロの展開を遅らせることで、期待しないタイミングでマクロが再帰的に呼び出されてしまう、といったケースです。
    • トラブルシューティング: 問題を引き起こしているマクロの定義を注意深く確認し、再帰的な呼び出しや予期せぬ展開が発生していないか確認します。これは高度なデバッグが必要となることが多く、該当するマクロを最小限のコードで再現し、一つずつ要素を取り除いていく「最小限の作業例 (MWE: Minimal Working Example)」を作成するのが効果的です。
  • オンラインリソースを活用する: TeX StackExchangeなどのコミュニティや、TeX Wikiなどのオンラインリソースには、類似の問題と解決策が豊富に蓄積されています。エラーメッセージの一部を検索するだけでも、解決策が見つかることがあります。
  • MWE (Minimal Working Example) を作成する: 問題を最小限のコードで再現できるMWEを作成することは、問題の特定と解決に非常に役立ちます。余分なパッケージやコンテンツを一時的に削除し、エラーが再現する最小のコードを探します。
  • .logファイルを確認する: エラーメッセージの詳細や、警告などが.logファイルに記録されています。.logファイルは、より詳細なデバッグ情報を提供してくれます。
  • エラーメッセージをよく読む: LaTeXのエラーメッセージは、慣れれば非常に有益な情報を含んでいます。どの行でエラーが発生したか、どのような種類の問題か、といった手掛かりを探しましょう。


以下に、\protectの具体的なプログラミング例とその解説を示します。

最も基本的な例:見出しの中での保護

これは\protectが最もよく使用されるシナリオです。ユーザー定義の強調コマンドなどを見出しに含めると、目次で正しく表示されないことがあります。

\documentclass{article}
\usepackage{japanese-babel} % 日本語を使用する場合

% カスタムの強調コマンドを定義
\newcommand{\myemphasis}[1]{\textbf{\emph{#1}}}

\begin{document}

\tableofcontents % 目次を生成

% 問題が発生する可能性のあるセクション
\section{これは\myemphasis{重要な}セクションです}

% \protect を使用して問題を回避するセクション
\section{これは\protect\myemphasis{重要な}セクションです}

\end{document}

解説

  • \section{これは\protect\myemphasis{重要な}セクションです}: ここでは\myemphasisの直前に\protectが挿入されています。これにより、LaTeXは目次ファイルに\myemphasisをそのままの形で書き込むように指示されます。そして、実際に目次が表示される段階で\myemphasisが展開されるため、正しく太字斜体で表示されます。
  • \section{これは\myemphasis{重要な}セクションです}: この行では\protectがありません。LaTeXは、この見出しをそのまま目次ファイル(.toc)に書き込もうとしますが、\myemphasisは「脆弱な」コマンドであり、このコンテキストでの即時展開が問題を引き起こす可能性があります。結果として、目次で「重要な」が太字斜体にならない、あるいはコンパイルエラーが発生することがあります。
  • \newcommand{\myemphasis}[1]{\textbf{\emph{#1}}}: \myemphasisという新しいコマンドを定義しています。これは引数を太字かつ斜体にするものです。

キャプションの中での保護

図や表のキャプションも「移動引数」であり、同様の問題が発生しうる場所です。

\documentclass{article}
\usepackage{graphicx} % \includegraphics のため

\begin{document}

\listoffigures % 図のリストを生成

\begin{figure}[htbp]
    \centering
    \includegraphics[width=0.5\textwidth]{example-image-a} % 任意の画像ファイルを指定
    \caption{この図は\protect\textbf{素晴らしい}例です。} % \textbf を保護
    \label{fig:example}
\end{figure}

\end{document}

解説

  • \caption{この図は\protect\textbf{素晴らしい}例です。}: キャプション内で\textbfを使用しています。\textbfは通常頑丈ですが、特定の状況や古いLaTeXバージョンでは問題になることがあります。\protectを付けることで、図のリスト(\listoffiguresで生成される)においても「素晴らしい」が正しく太字で表示されることが保証されます。

\DeclareRobustCommand を使ってコマンド自体を頑丈にする

頻繁に利用するカスタムコマンドであれば、毎回\protectを付けるのは手間です。その場合、コマンド自体を「頑丈 (robust)」として定義することで、\protectなしで「移動引数」内で安全に使用できるようになります。

\documentclass{article}
\usepackage{japanese-babel}

% \newcommand の代わりに \DeclareRobustCommand を使用
\DeclareRobustCommand{\myrobustcommand}[1]{\textsf{#1}}

\begin{document}

\tableofcontents

% \protect なしでも安全に動作する
\section{このセクションは\myrobustcommand{頑丈な}コマンドを使っています}

\end{document}

解説

  • \DeclareRobustCommandは、特に多くの場所で「移動引数」に含める可能性のあるカスタムコマンドを定義する場合に非常に便利です。
  • \DeclareRobustCommand{\myrobustcommand}[1]{\textsf{#1}}: \newcommandの代わりに\DeclareRobustCommandを使用しています。これにより、\myrobustcommandは最初から「頑丈な」コマンドとして定義され、\sectionなどの「移動引数」内で使用されても、\protectを明示的に付けなくても問題なく機能します。目次にも正しく表示されます。

\footnoteは非常に脆弱なコマンドであり、見出しに含める場合はほぼ確実に\protectが必要です。

\documentclass{article}
\usepackage{japanese-babel}

\begin{document}

\tableofcontents

% 脚注を見出しに含める場合
\section{見出しに脚注を\protect\footnote{これは脚注のテキストです}含める}

\end{document}

解説

  • \section{見出しに脚注を\protect\footnote{これは脚注のテキストです}含める}: \footnoteは、それが含まれる場所から離れたページのフッターにテキストを配置する複雑な処理を行います。このため、目次を生成する際に\footnoteが展開されてしまうと、不正なTeXコードが生成される可能性があります。\protect\footnoteの直前に置くことで、この問題を回避し、脚注が正しくページフッターに表示され、目次には脚注記号が表示されない(またはその部分が適切に処理される)ようになります。

\protectの主な目的は、LaTeXが.auxファイルなどに情報を書き出す際に、脆弱なコマンドが予期せず展開されてエラーや表示の崩れを引き起こすのを防ぐことです。

  • \DeclareRobustCommandの活用:
    • 頻繁に「移動引数」で使用するカスタムコマンドを定義する場合は、\DeclareRobustCommandを使って最初から頑丈なコマンドとして定義することを検討すると良いでしょう。これにより、\protectを毎回書く手間が省けます。
  • いつ\protectを使うか?:
    • ユーザー定義のマクロや一部のLaTeXコマンド(特に\footnoteなど)を、見出し、キャプション、目次、リストの項目など、「移動引数」と呼ばれる場所で使用する場合。


  • より高度な展開制御: \unexpanded\protected プリミティブ。これらは通常、パッケージ開発者が複雑なマクロを設計する際に使用する低レベルなツールです。一般的なユーザーが直接触れる機会は少ないでしょう。
  • PDFしおりの問題解決: \texorpdfstring。特にhyperrefパッケージを使用している場合に、PDFのしおりで特殊なコマンドが原因で表示がおかしくなる問題を解決します。
  • 最も推奨される代替手段: \DeclareRobustCommand。カスタムマクロを定義する際にこれを使用すれば、ほとんどの場合で\protectを意識する必要がなくなります。