In der Regel wird dies durch Syntaxfehler verursacht (im Gegensatz zu semantischen Fehlern).
Syntaxfehler können den Compiler verwirren. Genauer gesagt können sie dazu führen, dass sein interner Zustand nicht dem entspricht, was der Code sein soll. Das Ergebnis kann eine Kaskade scheinbar nicht zusammenhängender Fehlermeldungen sein.
Ein kleines Beispiel mit gcc (ähnliche Überlegungen werden wahrscheinlich andere Compiler anzuwenden):
#include <stdio.h>
int main(void)
char s = "Hello, world";
puts(s);
}
Dies hat zwei Fehler: eine fehlende {
und einen falschen Typ für s
(es muss char*
sein, nicht char
).
Ein wirklich cleverer Compiler könnte herausfinden, wo das fehlende {
sein muss, schlagen vor, es an diesem Punkt hinzuzufügen, und weitermachen, um den Rest der Datei zu kompilieren, vorausgesetzt, dass es da ist. Keine Kritik an gcc gedacht, aber es ist nicht ganz so clever:
c.c: In function ‘main’:
c.c:3:5: error: parameter ‘s’ is initialized
char s = "Hello, world";
^
c.c:4:5: error: expected declaration specifiers before ‘puts’
puts(s);
^
c.c:5:1: error: expected declaration specifiers before ‘}’ token
}
^
c.c:2:5: error: old-style parameter declarations in prototyped function definition
int main(void)
^
c.c:5:1: error: expected ‘{’ at end of input
}
^
Ohne die {
eine Erklärung von char s;
wäre tatsächlich syntaktisch gültig an diesem Punkt, wie ein alter Stil (pre-ANSI) Parameterdeklaration. GCC (etwas vernünftig) geht davon aus, dass es das ist, und beschwert sich über den Initialisierer - aber nicht über den falschen Typ des Initialisierers. Es diagnostiziert den Aufruf puts
als etwas, das nicht in einer alten Parameterliste angezeigt werden sollte, und schließlich beschwert über die fehlende {
am Ende der Datei.
Da es den beabsichtigten Kontext der Deklaration s
nicht kannte, diagnostiziert es die anderen Probleme nicht ordnungsgemäß.
Nachdem wir die {
an der richtigen Stelle hinzufügen, gcc in der Lage, korrekt die verbleibenden Probleme zu diagnostizieren:
c.c: In function ‘main’:
c.c:3:14: warning: initialization makes integer from pointer without a cast [enabled by default]
char s = "Hello, world";
^
c.c:4:5: warning: passing argument 1 of ‘puts’ makes pointer from integer without a cast [enabled by default]
puts(s);
^
In file included from c.c:1:0:
/usr/include/stdio.h:695:12: note: expected ‘const char *’ but argument is of type ‘char’
extern int puts (const char *__s);
^
In komplexeren Fällen Sie mehrere Pässe benötigen eine saubere Zusammenstellung zu erhalten. Auf der anderen Seite ist der Compiler manchmal in der Lage, Daten wiederherzustellen und weiter zu analysieren - aber die Syntax von C ist so, dass solche Wiederherstellungsversuche sehr oft fehlschlagen.
Eine Faustregel: Wenn der Compiler einen Syntaxfehler meldet, beheben Sie den ersten gemeldeten Syntaxfehler und kompilieren Sie. Wenn vor dem ersten Syntaxfehler mehrere nicht syntaktische Fehler auftreten, können Sie sie auch beheben. Alle Diagnosemeldungen, die einem Syntaxfehler folgen, sind nicht vertrauenswürdig. (Das ist nicht 100% wahr; manchmal können solche Nachrichten nützlich sein, so dass sie auf ein Problem zeigen, das Sie beheben können, und beheben Sie es vor dem erneuten Kompilieren.)
Dies erfordert, zu wissen, wie Syntaxfehlermeldungen zu erkennen sind. Einige Compiler enthalten möglicherweise das Wort "Syntax" in der Fehlermeldung, aber wie Sie sehen können gcc nicht. Wenn gcc sagt Ihnen, dass es erwartet ein bestimmtes Element, das ist eine Syntax-Fehlermeldung.
Eine andere Sache, auf die Sie achten sollten, ist, dass die Syntaxfehlermeldung möglicherweise nicht auf das tatsächliche Problem zeigt, wie in diesem Fall. Sie müssen möglicherweise einige Zeilen (oder viele Zeilen) von dem Punkt, an dem der Fehler gemeldet wird, nachsehen, um zu sehen, was den Fehler verursacht hat. Ein kleiner Fehler in einer C-Quelldatei kann ihn in etwas verwandeln, das immer noch syntaktisch Wert ist, oder fast gültig, aber mit einer ganz anderen Bedeutung. Fehlende Semikolons sind eine häufige Ursache für diese Art von Problem. Nicht übereinstimmende Kommentartrennzeichen sind ein anderes.
Andere Tools, wie IDEs oder Editoren mit Syntaxhervorhebung, können helfen, Syntaxfehler vor dem Kompilieren zu erkennen.
Klingt so, als müssten Sie an Ihren Tippgewohnheiten arbeiten. Und schreiben Sie auch nicht Tausende von Codezeilen zwischen den Kompilierungen. Schreiben Sie etwas kompilieren, schreiben Sie etwas kompilieren. Hinweis: Beginnen Sie am Anfang der Fehlerliste, nicht am Ende. vielleicht nur ein oder zwei reparieren und dann neu kompilieren. –
@dwelch In diesem speziellen Projekt wurde ungewöhnlich viel Code geschrieben, bevor die Kompilierung aus idiosynkratischen Gründen versucht wurde. Normalerweise kompiliere ich mehr inkrementell. –
und solche Probleme werden bei solchen Projekten, der Natur des Biests, passieren. Gleiches gilt für die Portierung eines großen Projekts von einem Ziel auf ein anderes. Sie müssen nur die Tausende von Fehlern einzeln oder zu einem bestimmten Zeitpunkt durcharbeiten. –