Konflikt zwischen Listings und Hyperref: „lstnumber.-14.11“ referenziert, existiert aber nicht

Konflikt zwischen Listings und Hyperref: „lstnumber.-14.11“ referenziert, existiert aber nicht

Ich sehe die folgenden Fehlermeldungen von pdflatex bei einem wirklich riesigen Projekt:

(see the transcript file for additional information)pdfTeX warning (dest): name
{lstnumber.-14.11} has been referenced but does not exist, replaced by a fixed 
one

pdfTeX warning (dest): name{lstnumber.-18.22} has been referenced but does not 
exist, replaced by a fixed one

pdfTeX warning (dest): name{lstnumber.-9.40} has been referenced but does not e
xist, replaced by a fixed one

pdfTeX warning (dest): name{lstnumber.-4.3} has been referenced but does not ex
ist, replaced by a fixed one

Der Anfang meiner Hauptdatei sieht folgendermaßen aus:

\documentclass[ebook,10pt,oneside,final]{memoir}
\usepackage{microtype}

% support for code listings
\usepackage[final]{listings}
\include{autodedent}
\lstset{
  basicstyle=\ttfamily\footnotesize,
  numberstyle=\footnotesize,
  breaklines=true,
  numbers=left,
  firstnumber=1,
  rangeprefix=//,
  includerangemarker=false
}

% support for indexing
\usepackage{makeidx}
\makeindex

% make _ a non-special character
\usepackage{underscore}

% support for cross-references
\usepackage{hyperref}
% \newcommand{\href}[2]{#2}

% fix spacing in \tableofcontents
\renewcommand\partnumberline[1]{#1\hspace{1em}}

% custom commands for use in the text of the book itself
\newcommand{\newterm}[1]{\textit{#1}}
\newcommand{\code}[1]{\mbox{\lstinline[basicstyle=\ttfamily]$#1$}}
\newcommand{\slurl}[1]{\href{https://#1}{\textsl{#1}}}
\newcommand{\codeblock}[2]{\label{foo#1#2}\hspace{1em}\lstinputlisting[linerange=ex#2-dex#2,autodedent]{examples-ch#1.cc}}
\newcommand{\codeblockref}[2]{\pageref{foo#1#2}}
\newcommand{\Csharp}{C\#}

\begin{document}

\frontmatter
\include{preface}
\tableofcontents

\mainmatter

% ...and so on...

Ein Beispiel \codeblockaus dem Haupttext:

Let's write a function to multiply each of the elements
in an array by 2.

\codeblock{1}{1}

Our function \code{double_each_element} works \emph{only} with objects of type
\code{array_of_int}...

Und ein Beispiel für \codeblockref:

Compare this version of the code to the version on page
\codeblockref{1}{1}.

Leider funktioniert es einwandfrei, wenn Sie nur diese Schnipsel in einer Testdatei zusammenstellen und ausführen pdflatex test.tex; pdflatex test.tex! (Außer, dass der Hyperlink bei der Nummer „1“ tatsächlich zum Inhaltsverzeichnis und nicht zu Seite 1 führt.) Aber wenn ich dasselbe im Maßstab mehrerer Kapitel mache, erhalte ich die Fehlermeldungen, die lstnumber.-14.11oben in dieser Frage zu sehen sind.

Ich habe herausgefunden, dass dies lstnumber.-<some number>das Format der vom listingsPaket automatisch generierten Etiketten ist. Daher gehe ich davon aus, dass es sich um eine fehlerhafte Interaktion zwischen listingsund hyperrefhandelt. Aber was genau läuft schief und was kann ich tun, um es zu beheben?


Das \hspace{1em}in meinem \codeblockMakro war mein naiver Versuch, den beschriebenen Fehler zu umgehenHier, falls das das Problem war.

Antwort1

Hier ist ein Beispiel, wie es meiner Meinung nach gemacht werden sollte:

Der Befehl wird angewendet, bevor das Makro verwendet wird, also bevor der Zähler erhöht wurde, um eine Referenzierung mit zu ermöglichen \codeblock– die Verwendung von „before“ ist ein sehr häufiger Fehler und daher werden die von geschriebenen Querverweisinformationen von einem potenziellen „before“ verwendet , das in Verbindung mit einem usw. Zähler stehen könnte , sodass die Informationen falsch sind und die Hyperanker-Koordinaten von einer älteren Ankerinstanz „before“ übernommen werden. Auf diese Weise verweisen die Links auf eine falsche Position zurück.\label\lstinputlistinglistings\refstepcounter\label\refstepcounter\label\refstepcountersection

Tatsächlich \lstinputlistingbesteht die label=Möglichkeit, den Etikettennamen anzugeben.

Das Folgende ist eine sehr reduzierte Form, die von Nicht-MWE bereitgestellt wird, aber funktioniert.

\documentclass[ebook,10pt,oneside,final]{memoir}
\usepackage{microtype}

% support for code listings

\begin{filecontents}{examplehelloworld.c}
#include<stdio.h>

int main(int argc,char **argv)
{
  printf("Hello World!\n");
  return(0);
}
\end{filecontents}

\usepackage[final]{listings}
%\include{autodedent}
\lstset{
  basicstyle=\ttfamily\footnotesize,
  numberstyle=\footnotesize,
  breaklines=true,
  numbers=left,
  firstnumber=1,
  rangeprefix=//,
  includerangemarker=false
}

% support for indexing
\usepackage{makeidx}
\makeindex

% make _ a non-special character
\usepackage{underscore}

% support for cross-references
\usepackage{hyperref}
% \newcommand{\href}[2]{#2}

% fix spacing in \tableofcontents
\renewcommand\partnumberline[1]{#1\hspace{1em}}

% custom commands for use in the text of the book itself
\newcommand{\newterm}[1]{\textit{#1}}
\newcommand{\code}[1]{\mbox{\lstinline[basicstyle=\ttfamily]$#1$}}
\newcommand{\slurl}[1]{\href{https://#1}{\textsl{#1}}}
\newcommand{\codeblock}[2]{\hspace{1em}\lstinputlisting[language={C},label={lst:#1-#2}]{examplehelloworld.c}}
\newcommand{\codeblockref}[2]{\pageref{lst:#1-#2}}
\newcommand{\Csharp}{C\#}


\usepackage{blindtext}

\begin{document}

\frontmatter
%\include{preface}
\tableofcontents

\mainmatter


\blindtext[3]


Reference: \codeblockref{1}{4}

\blindtext[5]


\codeblock{1}{4}



\end{document}

Antwort2

Beim Posten dieser Frage bin ich über die Antwort gestolpert! (Nicht, dass ich es verstehe.WarumEs klappt...)

Wenn Sie nur diese Schnipsel in einer Testdatei zusammenstellen und ausführen, pdflatex test.tex; pdflatex test.texfunktioniert es einwandfrei! (Außer, dass der Hyperlink bei der Nummer „1“ tatsächlich zum Inhaltsverzeichnis und nicht zu Seite 1 führt.)

Als Fehler auftraten, war ich nicht überrascht, dass der Hyperref an die falsche Stelle ging. Beim reduzierten Testfall war ich jedoch verwirrt. Also las ich überDasProblem, und fand heraus, dass das, was ich wollte \phantomsection, so war:

\newcommand{\codeblock}[2]{\phantomsection\label{lst:#1-#2}\lstinputlisting[linerange=ex#2-dex#2,autodedent]{examples-ch#1.cc}}
\newcommand{\codeblockref}[2]{\pageref{lst:#1-#2}}

Beachten Sie, dass mein Cargo-Kult \hspace{1em}(soweit ich weiß) nicht mehr benötigt wird und ich die Sonderzeichen, die ich beim Versuch, den Testfall zu reduzieren, lst:#1-#2durch ersetzt hatte, wieder einfügen konnte.foo#1#2

...Und wie durch Zauberei wird mein riesiges Projekt plötzlich einwandfrei kompiliert! Keine mysteriösen Fehlermeldungen mehr. Alle Hyperref-Links führen zu den richtigen Seiten und zeigen den richtigen Textkörper an.

Ich habe keine Ahnung, warum das Weglassen \phantomsectionsolches Chaos verursacht hat, aber nachdem ich es eingefügt habe, war alles behoben!

verwandte Informationen