Problemsammlung zum Knobeln? <-> Nettes kleines Anfängerproblem...



  • Vielleicht steh ich nur auf dem Schlauch aber ich finde den Fehler nicht. Könntest du ihn mal genauer erklären?



  • Hehe, jaja es sind immer die ganz kleinen, dummen Fehler, die einem Kopfzerbrechen bereiten. Wer den Fehler nicht findet soll sich Zeile 4 genauer ansehen und sich fragen, welche Auswirkungen diese Zeile auf die folgenden Zeilen hat.

    ------------------------------------------------------------

    Lösung:

    for (pVector = pVList; pVector != NULL; pVector = pVector->pNext);
    

    Hier ist am Ende ein Semikolon zu viel. Dies führt dazu, dass die dynamische Liste durchlaufen wird, ohne das etwas gemacht wird. Zum Ende hat pVector den Wert NULL (Abbruchbedingung).

    Interessant ist nun, dass nun aber der Code in Zeile 6 ausgeführt wird, welcher (pVector hat den Wert NULL) eine Segmentation Fault hervorruft.



  • isam2k wrote: "-> Ihr macht beim Programmieren einen Fehler, den ihr sehr lange suchen musstet, und bei dem nicht auf den ersten Blick klar war, was denn nun falsch war (nicht Banalitäten wie Semikolon vergessen)."

    isam2k wrote: Lösung : "Hier ist am Ende ein Semikolon zu viel."

    AIG

    ALLES IST GUT 🙂



  • *facepalm* Bin ich so blöd.
    Aber das sind wirklich Fehler bei denen man lange grübelt bis man sie findet (Der Debugger hilft da viel)



  • isam2k schrieb:

    Hier ist am Ende ein Semikolon zu viel.

    Ich könnte wetten, dass es vorhin noch nicht da war 😉

    Habe es auch total übersehen...


  • Mod

    linux_c89 schrieb:

    *facepalm* Bin ich so blöd.
    Aber das sind wirklich Fehler bei denen man lange grübelt bis man sie findet (Der Debugger hilft da viel)

    Oder auch ein Compiler. Es gibt da so etwas wie Warnungen...



  • Mein Compiler gab keine Warnung. ist aber auch vc6



  • Naja bei sowas warnt der Compiler aber nicht. Also zumindest das hier geht ohne Warnung

    int main()
    {
    	int i=5;
    	while(i) ;
    		i--;
    	return 0;
    }
    

    Mit aufruf

    gcc -Wall test.c
    

    ich meine so eine Konstruktion kann doch Absicht sein, wieso sollte er warnen? Ich denke da an sowas

    int main()
    {
            int i=0;
            while(i--);
                    /*was auch immer */
            return 0;
    }
    

    Ein Compiler der mich vor sowas warnt kommt in die Tonne (und die Einrückung beim Kommentar würde ich natürlich nicht machen, hier gehts nur um Analogie zum 1. Beispiel)



  • Ich bin mal verzweifelt warum eine Funktion nicht richtig funktioniert hat. Ich habe Code umgestellt und so weiter... Irgendwann hatte ich die Lösung: Ich hab einfach vergessen die Funktion aufzurufen...



  • Blind ... schrieb:

    isam2k schrieb:

    Hier ist am Ende ein Semikolon zu viel.

    Ich könnte wetten, dass es vorhin noch nicht da war 😉

    Habe es auch total übersehen...

    daaas semikolon war da 🙂

    @niggelchen: ja ich weiss, hab auch gezögert, aber als ich den fehler zum ersten mal bemerkte dacht ich einfach: "ja schön, ein semikolon zu viel", um dann aber drauf zu kommen warum hier jedesmal eine segmentation fault ausgegeben wurde musst ich noch lange grübeln (anfänger halt).
    aufgrund der struktur des codes hat es mich sehr verwundert, dass ohne warnung einfach bei zeile 6 weitergemacht wird.
    hab schlussendlich 2 stunden damit verbracht in meinem code nach einer stelle zu suchen, an der ich das attribut pNext nicht richtig mit NULL oder einer existierenden struktur definiert hatte.



  • Wobei NULL bei dir ein normaler Fall ist und damit eigentlich vom Programm behandelt werden sollte. Sonst wäre folgende Abbruchbedingung richtig gewesen. Ob du nun ein Segfault oder Deadlock bekommst, ist ja egal 😉 . Du müsstest in jedem Fall vorher sicher stellen, dass auch die Bedingung erfüllt ist. Und dann wäre auch dein Semikolon wieder richtig am Platz. Sicherer und deswegen geben einige Compiler auch eine Warnung aus, ist es aber ein Anweisungsblock zu schreiben. Auch wenn du nur eine oder keine Zeile danach hast. So vermeidest du es auch die Klammern zu vergessen, wenn du noch weitere Anweisungen hinzufügen willst. Dass ist dann so ein Punkt, wo auch Makros gerne mal ihrem Ruf gerecht werden und richtig schön ins Auge gehen können.

    vector_t *fnGetVector(vector_t *pVList, int iVectI)
    {
        vector_t *pVector;
        for (pVector = pVList; pVector->iVectI != iVectI; pVector = pVector->pNext) {}
        return pVector;
    } // fnGetVector
    


  • ass ist dann so ein Punkt, wo auch Makros gerne mal ihrem Ruf gerecht werden und richtig schön ins Auge gehen können.

    Hier sind natürlich nur schlecht programmierte makros gemeint, eigentlich ist es gängige Praxis jedes Makro mit mehr als einem Befehl mit einem do{ }while(0); zu umschließen
    Ob man jetzt bei nur einem Befehl die geschweiften Klammern macht oder weglässt ist Geschmacksfrage, da sind schon erbitterte Religionskriege drum geführt worden (ich bevorzuge z.B. das Weglassen, weil ichs dann schöner zu lesen finde. Die Autoeinrückung meines Editors(vim) hilft da auch Fehler zu erkennen



  • Gibt es einen Grund warum man do{}while(0) schreibt? Man könnte doch genauso gut if(!0){} schreiben? Ich selber nutze sogar nur geschweifte Klammern. Hat eine dieser Varianten Vorteile/Nachteile? Oder ist das gar so festgelegt, wie eine for-Schleife mit leerer Bedingung, die einzig wahre Endlosschleife sein soll?



  • Man kann eine Endlosschleife auf verschiedene Weisen kreieren.

    Am häufigsten ist wohl:
    `for ( ;; )

    {

    }`

    Oder:
    `

    while (1)

    {

    }`

    Und nur mit if (...) {] kannst du keine Schleife realisieren.



  • kkkk schrieb:

    Am häufigsten ist wohl:
    `for ( ;; )

    {

    }`

    Mein letzter Stand dazu war, dass das die Endlosschleife ist. Das soll irgendwo im Standard definiert sein oder so ähnlich.

    kkkk schrieb:

    Und nur mit if (...) {] kannst du keine Schleife realisieren.

    Nein, genauso wenig wie mit do {} while (false); 😉 Was aber auch nicht der Sinn der Sache ist. Es geht hier eher um einen gültigen Ausdruck, mit dem man das Makro kapseln kann. Mein Bedenken wäre jetzt, dass es Fälle gibt, wo nur geschweifte Klammern einen falschen Effekt haben. Nur will mir da keiner einfallen, deswegen nutze ich das immer noch. Als ich das erste mal diesen while (false) Ausdruck gesehen habe, dachte ich zuerst, da will jemand die Ausführung unterbinden. Man kann den Leser mit einem ungünstigen Ausdruck sehr leicht verwirren.



  • Naja wenn man mal weiß, das das ein Makro kapselt ist das leicht verständlich (man muss es halt mal wissen...)
    if benutzt man glaub ich nicht weil ja eventuell ein else folgen könnte , also sowas

    #define MACRO_DO do { puts("hallo"); puts("Welt"); }while(0);
    #define MACRO_IF if(1){ puts("hallo"); puts("Welt"); }
    /* ... */
    if(var)
            MACRO_IF
    else /*blablabla */
    

    Das else würde dann hier mit MACRO_IF zusammengehen, was nicht beabsichtigt ist. Mit MACRO_DO passiert nix schlimmes


Anmelden zum Antworten