Compilerfehlern, Linkerfehlern und Ausführungsfehler



  • Hi Leute,

    ich bin noch relativ neu und wollte mal fragen ob mir jemand den Unterschied zwischen einem Compiler- / Linker- / Ausführungsfehler erklären kann?

    Ein Compilerfehler ist doch nichts anderes, als ein Programmierfehler, sehe ich das richtig?

    z.B. Wenn ich einen ; vergesse, gibt der Compiler mir einen Fehler aus, weil er die "Syntax" meiner Eingabe nicht kennt, bzw. nicht weiß, wie er die Hochsprache in eine maschinenverständliche Sprache übersetzen soll?

    Wo ist jetzt der Unterschied zu einem Linkerfehler?

    Wenn ich ein Programm erstelle, wird ja zu erst der Präprozessor aufgerufen, der z.B. Kommentare entfernt / Makros ersetzt. Anschließend wird dieser Quellcode an den Compiler übermittelt. Wenn der Text Fehlerfrei ist, werden die einzelnen Dateien zusammengebunden (durch den Linker).

    Was können hierbei für Fehler auftreten? (fehlende Headerincludes vielleicht?)

    Wie der Name schon sagt, wird sich ein Ausführungsfehler erst zur Laufzeit des Programms bemerkbar machen. Da der Compiler sämtliche fehlerhaften Befehle bemängelt handelt es sich hierbei wahrscheinlich um Logikfehler, die der Compiler nicht erkennen kann, wie z.B. das überschreiten von arraygrenzen?

    mit freundlichen Grüßen,

    Martin14



  • Martin14 schrieb:

    Wenn der Text Fehlerfrei ist, werden die einzelnen Dateien zusammengebunden (durch den Linker).

    Was können hierbei für Fehler auftreten? (fehlende Headerincludes vielleicht?)

    Wenn du eine Library oder eine Objekt- (bzw auch C-) Datei nicht angegeben hast.

    Eine Variablen-/Funktionsdefinition im Header und der Header wird in verschieden Dateien eingebunden.
    Ein extern ohne entsprechende Definition.



  • Martin14 schrieb:

    in Compilerfehler ist doch nichts anderes, als ein Programmierfehler, sehe ich das richtig?
    [...]
    Wie der Name schon sagt, wird sich ein Ausführungsfehler erst zur Laufzeit des Programms bemerkbar machen. Da der Compiler sämtliche fehlerhaften Befehle bemängelt handelt es sich hierbei wahrscheinlich um Logikfehler, die der Compiler nicht erkennen kann, wie z.B. das überschreiten von arraygrenzen?

    ja, obwohl ich von einem Programmierfehler eher bei einer inkorrekten Implementierung bzw. falscher Anwendung sprechen würde und führt nicht zwangsläufig zu einem Laufzeitfehler. Wie z.B. du schreibst sowas wie

    int fact(int n)
    {
        int x = 1;
        int i;
    
        for(i = 2; i < n; ++n)
            x *= i;
    
        return n;
    }
    

    Der Compiler wird nicht meckern, weil die Syntax OK ist. Du wirst auch keine Laufzeitfehler bekommen sondern nur ein falsches Ergebnis. Das nenne ich einen Programmierfehler, weil die Implementierung fehlerhaft ist.

    Programmierfehler können aber auch zu Laufzeitfehler führen, wie z.B.

    char *capitalize(char *str)
    {
        if(str == NULL || *str == 0)
            return str;
    
        *str = toupper(*str);
    
        return str;
    }
    
    void foo()
    {
        printf("%s\n", capitalize("hello world"));
    }
    

    Der Compiler wird nicht meckern, weil die Syntax OK ist. Du wirst aber einen Laufzeitfehler bekommen (segfault). Hier gibt es per se keine falsche Implementierung des Algorithmus; die Art und Weise wie du aber capitalize aufrufst ist fehlerhaft.

    Martin14 schrieb:

    Wenn ich ein Programm erstelle, wird ja zu erst der Präprozessor aufgerufen, der z.B. Kommentare entfernt / Makros ersetzt. Anschließend wird dieser Quellcode an den Compiler übermittelt. Wenn der Text Fehlerfrei ist, werden die einzelnen Dateien zusammengebunden (durch den Linker).

    Was können hierbei für Fehler auftreten? (fehlende Headerincludes vielleicht?)

    fehlende Headerincludes gehören zu den Compilerfehlern, da die includes durch den Präprozessor verarbeitet werden, also gehört noch zum Compilerprozess (theoretisch vor dem Kompilieren)

    dein Code ruft die Funktion foo(); auf, die erst in mylib-1.2.3 eingeführt wurde, du linkst aber gegen mylib-1.2.2 , der Linker kann in der Bibliothek die Funktion foo(); nicht finden und teilt dir das mit. Das ist z.B. ein Linkfehler.

    oder du kompilierst eine 32bit App und linkst gegen mylib-1.2.3 , die nur als 64-bit vorhanden ist, da wird der Linker wieder meckern.


  • Mod

    Das trifft es schon ziemlich gut. Eine gute Analogie für den Quellcode eines Computerprogramm ist ein Buch. Am besten ein Theaterstück oder auch ein Kochbuch. Denn letztlich ist der Quellcode eines Computerprogramms ein Schriftstück in einer bestimmten Sprache mit dem der Autor bestimmte Sachverhalte ausdrücken möchte. Der Compiler ist ein Übersetzer in eine andere Sprache. Der Linker bindet verschiedene Kapitel zu einem lesbaren Buch zusammen. Der Computer "liest" das Buch, wenn er das fertige Programm ausführt und setzt das gelesene um; er führt das Theaterstück auf oder kocht nach dem Rezept.

    Compilerfehler sind Fehler in der Benutzung der Sprache. Die Grammatik ist falsch; du benutzt Wörter, die es nicht gibt; Rechtschreibfehler. Solche Dinge. Der Compiler kann dies nicht in eine andere Sprache übersetzen, da die Vorlage einfach falsch ist und er nicht verstehen kann, was gemeint ist. "Hund halb fünf?? daru"

    Fehler zur Ausführungszeit sind darauf zurück zu führen, dass der Inhalt falsch ist. Logikfehler; falsche Behauptungen; oder auch einfach nur totaler Nonsens. "Läute die grünen Einsen neben den Bohneneintopf" ist grammatikalisch vollkommen richtig, ist aber Unsinn; wer nach diesem Rezept kocht, wird ebenfalls Unsinn erhalten.

    Linkerfehler sind fehlerhafte Verweise. Der Linker ist der Buchbinder/Schriftsetzer. Der Compiler erzeugt bei seiner Übersetzungsarbeit Verweise der Art "Siehe Abbildung {image:abc}", da er noch nicht weiß, wo {image:abc} im fertigen Buch genau stehen wird. Der Linker möchte daraus etwas wie "Siehe Abbildung 7 auf Seite 628" machen. Wenn es jedoch nirgendwo eine Abbildung mit der internen Kennzeichnung {image:abc} gibt (oder wenn es uneindeutig ist, da es mehrere dieser Abbildungen gibt), dann scheitert der Vorgang.

    fehlende Headerincludes vielleicht?

    Eher das Gegenteil. In Headern werden Dinge bekannt gemacht ("Es gibt ein Bild mit der Kennzeichnung {imgae:abc}"). Dadurch ist es dem Compiler möglich, die dort verwiesenen Dinge zu nutzen, ohne dass sie ihm konkret vorliegen. Beispielsweise reicht es dem Compiler zu wissen, dass es eine Funktion

    double cos(double arg);
    

    gibt, um Code übersetzen zu können, der diese Funktion benutzt. Der Compiler muss dazu nicht wissen, was cos macht oder wie es genau funktioniert, er fügt in seine Ausgabe einfach einen Verweis auf die Funktion cos ein. Wenn der Linker dann die verschiedenen Übersetzungseinheiten zu einem ausführbaren Programm zusammen bindet, dann muss er aber irgendwo die konkrete Funktion cos vorfinden (und zwar genau einmal!), sonst kann er den Verweis nicht auflösen.



  • SeppJ schrieb:

    oder auch einfach nur totaler Nonsens. "Läute die grünen Einsen neben den Bohneneintopf"

    Einsen im Bohneneintopf, Mann jetzt habe ich aber Hunger gekriegt 🤡


  • Mod

    supertux schrieb:

    SeppJ schrieb:

    oder auch einfach nur totaler Nonsens. "Läute die grünen Einsen neben den Bohneneintopf"

    Einsen im Bohneneintopf, Mann jetzt habe ich aber Hunger gekriegt 🤡

    Das zeigt gut den Unterschied zwischen dir und einem Computer. Die Einsen sind weder "im" Eintopf (sondern neben), noch "sind" sie überhaupt (sondern "läuten"). Ein Computer nimmt eben alles absolut wortwörtlich, du kannst dir hingegen ausmalen, was der Autor wohl gemeint haben könnte.

    Daher auch der oft genannte Hinweis:

    c.rackwitz schrieb:

    Code ist kein Haufen von wahllos zusammengeschmissenen Buchstaben und Zeichen, Code ist Logik pur. Du musst genau wissen, warum du wo und welches Zeichen setzt.



  • Hey das ging aber schnell 😋

    Danke euch für die extrem guten und einleuchtenden Beispiele 😉

    mfg

    Martin14



  • Gehe ich recht in der Annahme, dass in c++ das Werfen einer Ausnahme ohne eine anschließende catch Anweisung ebenfalls als compiler Fehler zählt, oder ist es nicht zwingend notwendig eine Ausnahme auch zu fangen?

    mit freundlichen Grüßen,



  • Eine nicht gefangene geworfene Ausnahme führt zu einer Fehlermeldung des Laufzeitsystems.



  • Martin14 schrieb:

    Gehe ich recht in der Annahme, dass in c++ das Werfen einer Ausnahme ohne eine anschließende catch Anweisung ebenfalls als compiler Fehler zählt, oder ist es nicht zwingend notwendig eine Ausnahme auch zu fangen?

    mit freundlichen Grüßen,

    ein Compilerfehler ist, wenn der Compiler meckert und nicht weitermacht.


Anmelden zum Antworten