Calloc Array macht Probleme



  • Hallo Leute,

    ich habe ein Problem mit einem 2D Array. Ich initialisiere es, kann es aber anschließend nicht mehr korrekt ansprechen. Anbei der Code:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(){
    unsigned long fMaxNodeConnectedElements = 4, fnNode = 16;
    unsigned long fi=0, fj=0;
    unsigned long **fpElementsOnNode = (unsigned long **)calloc(fMaxNodeConnectedElements, sizeof(unsigned long *));
    
    while(fi++<=fMaxNodeConnectedElements){
    	fpElementsOnNode[fi] = (unsigned long *)calloc(fnNode+1, sizeof(unsigned long));
    }
    fi=0;
    printf("fMaxNodeConnectedElements: %lu\n", fMaxNodeConnectedElements);
    printf("fnNode: %lu\n\n\n", fnNode);
    for (fi=0;fi<fMaxNodeConnectedElements-1;fi++){
    	for (fj=0;fj<fnNode;fj++){
    		printf("Index 1: %lu, Index 2: %lu\n", fi, fj);
    		fpElementsOnNode[fi][fj]=0;
    	}
    }
    }
    

    Das ganze ist ein einfaches Beispiel, welches das Problem jedoch gut abbildet.
    Das erste printf in Zeile 13 liefert eine 4. Das printf in Zeile 14 liefert eine 16. Gut, alles andere wäre ja auch Quatsch. Anschließend wir nurnoch einmal das printf aus Zeile 17 mit "Index 1: 0, Index 2: 0" ausgegeben. Sodann erhalte ich Segment violation.
    Wenn ich die Indizes in Zeile 18 vertausche, geschieht das gleiche.

    Sieht jemand den Fehler?

    Grüße,
    CJens.


  • Mod

    In Zeile 9 gehst du über die Indizes 1 bis fMaxNodeConnectedElements+1.

    Was sollen die Casts in Zeile 7 und Zeile 10? Das funktioniert zwar auch in C, aber ist C++-Syntax. In C verdeckt man dadurch aber mögliche Fehler, vor denen der Compiler sonst warnen würde. Und in C++ würde man alles ganz anders machen.

    Wenn ich die Indizes in Zeile 18 vertausche, geschieht das gleiche.

    Du sollst nicht raten, du sollst nachdenken! 🙂 Oder wenn das nicht hilft, einen Debugger benutzen 🕶 . Ein ganz wunderbares Werkzeug (man sagt, es sei das wichtigste Werkzeug des Programmierers), mit dem du Schritt für Schritt Fehler nachvollziehen kannst. Dein kleines Progrämmchen ist fast ideal, um dich mal damit vertraut zu machen. daher empfehle ich dir, trotzdem mal den Fehler im Debugger zu analysieren, obwohl ich dir schon verraten habe, was falsch ist.



  • Hallo Sepp,

    danke für die Tipps. Aber geholfen hat es nicht. Raten ist nicht die richtige Methode, das glaube ich Dir. Wenn man aber über Stunden den Fehler nicht findet...

    Das mit den Indizes wars nicht. Folgender Code bringt den gleichen Fehler:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(){
    unsigned long fMaxNodeConnectedElements = 4, fnNode = 16;
    unsigned long fi=0, fj=0;
    unsigned long **fpElementsOnNode = (unsigned long **)calloc(2000, sizeof(unsigned long *));
    
    while(fi++<=1000){
    	fpElementsOnNode[fi] = (unsigned long *)calloc(fnNode+1, sizeof(unsigned long));
    }
    fi=0;
    printf("fMaxNodeConnectedElements: %lu\n", fMaxNodeConnectedElements);
    printf("fnNode: %lu\n\n\n", fnNode);
    for (fi=0;fi<fMaxNodeConnectedElements-1;fi++){
    	for (fj=0;fj<fnNode;fj++){
    		printf("Index 1: %lu, Index 2: %lu\n", fi, fj);
    		fpElementsOnNode[fi][fj]=0;
    	}
    }
    }
    

    Der Fehler entsteht in Zeile 18. Wenn ich die auskommentiere, läuft der Code durch...



  • Schon debugt?

    Das Problem ist die while-Schleife.
    Bau doch mal das

    printf("Index 1: %lu\n", fi);
    

    mit in die Schleife ein.
    Dann mach aber mal weniger Elemente, damit du den Anfang siehst.


  • Mod

    CJens schrieb:

    Das mit den Indizes wars nicht. Folgender Code bringt den gleichen Fehler:

    Jetzt läuft die Schleife ja auch von 1 bis 1000. 🙄 Warum nimmst du keine for-Schleife? Weißt du, was fi++ überhaupt macht?

    Der Fehler entsteht in Zeile 18. Wenn ich die auskommentiere, läuft der Code durch...

    Eben nicht. Der Fehler entsteht viel früher, in Zeile 18 äußert er sich bloß. Gerade deswegen habe ich dir den Debugger empfohlen, damit hättest du die Werte von fi kontrollieren können. Schade, dass du das nicht ausprobiert hast, selbst als es beim zweiten Versuch nicht funktioniert hat 😞



  • SeppJ schrieb:

    Jetzt läuft die Schleife ja auch von 1 bis 1000. 🙄

    Die fing auch in der ersten Version schon bei 1 an.
    Petze 🤡


  • Mod

    DirkB schrieb:

    SeppJ schrieb:

    Jetzt läuft die Schleife ja auch von 1 bis 1000. 🙄

    Die fing auch in der ersten Version schon bei 1 an.
    Petze 🤡

    Habe ich ihm oben schon gesagt, ganz am Anfang. Ich muss jedoch korrigieren: Sie geht jetzt von 1 bis 1001. Kleinergleich verwirrt mich immer, weil man es sonst fast nie benutzt.



  • Danke, dass ihr mir da helfen wollt, aber ich verstehe es nicht.

    Also, klar läuft die Schlefe jetzt bis 1000 bzw. 1001.
    Aber ich habe in Zeile sieben das Feld doch bis 2000 initialisiert (Achtung: habe den Code im Posting von 07:55:00 Uhr geändert).

    Ich verstehe das so. In Zeile 7 habe ich ein Feld mit Pointern von 0 bis 2000 initialisiert.
    Anschließend weiße ich jedem dieser Pointer (nicht jedem, sondern nur von 0 bis 1001) ein Array zu, da ein Array in C ja lediglich ein Pointer auf das erste Element ist.

    Ich habe leider keinen Debugger. Ich nutze Nodepad++ und habe da den LCC Compiler mit NPP_Exec eingefügt. Könnt ihr mir eine Debugger empfehlen? Problem ist, dass ich solche Debugger nur aus sehr umfangreichen Programmierumgebungen kenne (LCC32 oder Visual Studio C++) die mich auch etwas überfordern.

    Ihr könnt den Code doch einfach mal mit Copy Paste rauskopieren. Der enthält ja nur diese main-functionl.

    Nochmal danke,
    CJens



  • int main ( void )
    {
    	unsigned long imax = 2000, jmax = 16, i = 0, j = 0;
    	unsigned long **p = calloc ( imax, sizeof ( unsigned long* ));
    
    	while ( i < imax )
    		p [ i++ ] = calloc ( jmax, sizeof ( unsigned long ));
    
    	for ( i = 0; i < imax; i++ )
    		for ( j = 0; j < jmax; j++ )
    			printf ( "i: %lu, j: %lu\n", i, j ), p [ i ] [ j ] = 0;
        return 0;    
    }
    

    So läuft es. Deine ultralangen Bezeichner sind der Horror 😃
    Frag mich aber nicht warum es bei dir nicht läuft, durch die Änderung
    der Bezeichner habe ich den Zusammenhang zu deinem Code verloren.
    Du kannst ja die Änderungen Schritt für Schritt vornehmen und gucken wo es dann
    crasht.

    CJens schrieb:

    Anschließend weiße ich ...

    weise
    Die Zeiger werden nicht weiß eingefärbt. *SCNR*

    CJens schrieb:

    Ich habe leider keinen Debugger. Ich nutze Nodepad++ und habe da den LCC Compiler mit NPP_Exec eingefügt. Könnt ihr mir eine Debugger empfehlen?

    Ich benutze das Visual Studio, da ist ein Debugger mit drin.

    CJens schrieb:

    Problem ist, dass ich solche Debugger nur aus sehr umfangreichen Programmierumgebungen kenne (LCC32 oder Visual Studio C++) die mich auch etwas überfordern.

    So ähnlich habe ich auch mal gedacht und mit lange Zeit mit printf Ausgaben abgequält, weil ich keine Lust hatte mich in einen Debugger einzuarbeiten.
    Wenn du vor hast länger beim Programmieren zu bleiben, kann ich dir empfehlen
    dich so schnell wie möglich mit einem Debugger anzufreunden, weil es die
    Arbeit enorm erleichtert.
    Die Zeit, die für die Einarbeitung in den Debugger nötig ist, lohnt sich am Ende.

    Edits: Code beautifications.



  • Ich verstehe zwar noch immer nicht, wieso der Code vor allem im zweiten Posting nicht funktioniert hat, aber so funktioniert es:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(){
    unsigned long fMaxNodeConnectedElements = 4, fnNode = 16;
    unsigned long fi=0, fj=0;
    unsigned long **fpElementsOnNode = (unsigned long **)calloc(fMaxNodeConnectedElements, sizeof(unsigned long *));
    
    for (fi=0; fi<fMaxNodeConnectedElements;fi++){
    	printf("%lu\n", fi);
    	fpElementsOnNode[fi] = (unsigned long *)calloc(fnNode+1, sizeof(unsigned long));
    }
    fi=0;
    
    printf("fMaxNodeConnectedElements: %lu\n", fMaxNodeConnectedElements);
    printf("fnNode: %lu\n\n\n", fnNode);
    for (fi=0;fi<fMaxNodeConnectedElements;fi++){
    	for (fj=0;fj<fnNode;fj++){
    		printf("Index 1: %lu, Index 2: %lu\n", fi, fj);
    		fpElementsOnNode[fi][fj]=0;
    	}
    }
    
    system("PAUSE");
    }
    

    Vielen Dank Euch beiden.

    Das mit dem Debugger würde mich aber trotzdem noch interessieren. Gibt es einen, der nicht ein eine total überlaufene Programmierumgebung eingebettet ist?



  • Vielen Dank.

    Ja, dann werde ich wohl in den saueren Apfel beißen müssen und mir ne neue Lektüre zulegen um Visal Studio zu lernen... denn das hat mich jetzt zwei Tage aufgehalten.

    Grüße aus Berlin,
    CJens



  • CJens schrieb:

    Ich verstehe zwar noch immer nicht, wieso der Code vor allem im zweiten Posting nicht funktioniert hat, ...

    Dein Array wurde in der while-Schleife erst ab dem Index 1 (in Worten eins) beschrieben.
    D.h. dem Element 0 (Null) wurde kein Wert zugewiesen.

    fi = 0;
    while(fi++<=1000){ // Nach dem Vergleich wird fi verändert
        fpElementsOnNode[fi] = (...  // Also greifst du hier schon auf fpElementsOnNode[1] zu
    }
    

    Später Versuchst du dann aber von dem Element fpElementsOnNode[0] Daten zu lesen.



  • Danke Dirk.

    Das war der Fehler.

    👍



  • Dann lies dir nochmal den ersten Satz der ersten Antwort auf deine Frage durch:

    SeppJ schrieb:

    In Zeile 9 gehst du über die Indizes 1 bis fMaxNodeConnectedElements+1.


Anmelden zum Antworten