Programm-Absturz nach Einbinden von malloc()



  • Hi!
    Existiert der Zeiger ADatei vor dem fseek Zugriff?

    Bei deiner allokierung fällt auf, das du nicht die Rückgabewerte überprüfst, bevor du auf sie zugreifst; das sollte man auf jeden Fall machen.

    Die Funktion MallocFloatMatrix solltest du überdenken, es wird pro Spalte nur ein Speicherbereich für float reserviert. Außerdem kann zeilenAnz > spaltenAnz werden und ein Zugriff ala t[i] löst (im besten Fall) eine System-Speicherzugriffverletzung aus. Memset der Zeiger auf Zeiger ist nicht nötig, da kommen ja sowieso die Adressen der floats rein... -
    Kurz:
    Reserviere doch erst die Anzahl der Zeilen und dann für jede Zeile die Anzahl der Spalten.

    float** matrix = malloc ( zeilenAnz * sizeof(float*));
    if ( matrix == NULL ) // Rückgabewert prüfen.
    {
    // Fehlerbehandlung
    return 1;
    }
    
    // Für i = 0, i < zeilenAnz, also für jede Zeile werden die Spalten erzeugt.
    ...
    matrix[i] = malloc ( spaltenAnz * sizeof(float) );
    if ( matrix[i] == NULL ) // Rückgabewert prüfen.
    {
    // Fehlerbehandlung
    return 1;
    }
    

    Der Zugriff auf ein Matrixelement erfolgt dann nach (möglicherweise) gewohnter Art: matrix[zeile][spalte];

    mfg
    *0r



  • Hallo.

    Danke für eure schnelle Antwort.

    @VuurWerK:
    Der Umstieg auf calloc() hat keinen sichtbaren Erfolg gebracht.

    @*0r:
    Ja, der Zeiger ADatei existiert zu diesem Zeitpunkt bereits:

    ADatei=fopen(path_writedat, "wt"); // Datei öffnen
    if(ADatei==NULL) {
        printf("Erstellen der Ausgabedatei fehlgeschlagen!\n\n");
        fflush(stdin);
        getchar();
    }
    

    Ach ja ... das man das mit dem fflush(stdin) nicht macht ist mir bekannt und wird auch noch geändert. Hatte nur im Moment keine Priorität.

    Habe eine Überprüfung der Rückgabewerte eingefügt (mit printf). Sie schlägt aber nicht an.

    *0r schrieb:

    Die Funktion MallocFloatMatrix solltest du überdenken, es wird pro Spalte nur ein Speicherbereich für float reserviert. Außerdem kann zeilenAnz > spaltenAnz werden und ein Zugriff ala t[i] löst (im besten Fall) eine System-Speicherzugriffverletzung aus.

    Hier verstehe ich nicht ganz was du meinst. In jede Martix-Zelle soll ein float gespeichert werden, deshalb auch nur dieser Speicherplatz. Oder hab ich da was falsch verstanden?

    Vielleicht hilft der erste Aufruf der Funktion weiter. Er befindet sich wenige Zeilen vor dem "fseek" den ich im Start-Post gezeigt hatte.

    analysemem = MallocFloatMatrix(2, fenster);
    for(i=0; i<fenster; i++){
        analysemem[0][i]=0;
        analysemem[1][i]=0;
    }
    


  • @Blue][ce_: Ausser calloc habe ich noch mehr geschrieben, vergleich einfach mal mit Deinem Code.

    Gut Schuß
    VuuRWerK 😉



  • @VuuRWerK:

    Okay ... die for-Schleife hatte die falsche Variable.
    Habe das jetzt so umgesetzt:

    floatMatrix MallocFloatMatrix(int zeilenAnz, int spaltenAnz) {
    	float** t = malloc(zeilenAnz*sizeof(float*));
    	if (t == NULL){
    		printf("Boehse!");
    	}
    	int i;
      	for(i = 0; i < zeilenAnz; ++i){
        	t[i] = calloc(spaltenAnz, sizeof(float));
        	if (t[i] == NULL){
    			printf("Auch boehse!");
    		}
    	}
      return t;
    }
    

    Damit läuft das Programm tatsächlich ein paar Zeilen weiter. Danach hängt es sich aber wieder auf ... 😞
    Interessant daran ist, dass das Programm an ein paar "fprintf()"-Ausdrücken vorbeikommt, diese aber scheinbar nicht ausführt. Die Zieldatei bleibt leer.
    😕

    Grüße,
    Blue][ce



  • VuuRWerK schrieb:

    @Blue][ce_: Ausser calloc habe ich noch mehr geschrieben, vergleich einfach mal mit Deinem Code.

    Gut Schuß
    VuuRWerK 😉

    Das funktioniert zufällig, wenn sizeof(float) gleich sizeof(float*) ist. Probier das mal mit char** statt float**.

    Blue][ce_ schrieb:

    ...Hier verstehe ich nicht ganz was du meinst. In jede Martix-Zelle soll ein float gespeichert werden, deshalb auch nur dieser Speicherplatz. Oder hab ich da was falsch verstanden?
    ...

    Das ist nicht sinnvoll, da kannst du doch gleich ein eindimensionales float Array nehmen.
    Außerdem guck mal, siehst du das Problem bei deiner Vorgehensweise:

    spaltenAnz = 2;
    zeilenAnz = 3;
    float** t = malloc(spaltenAnz*sizeof(float*));
    
    for(i = 0; i < zeilenAnz; ++i)
        t[i] = malloc(sizeof(float));
    // Tipp: if i == 2 then RAM terr0r !
    

    ?

    Selbst wenn zeilenAnz == spaltenAnz wäre, auf deine Elemente kannst du bei deiner Vorgehensweise nur so zugreifen:
    t[0][0], t[1][0], ... , t[spaltenAnz-1][0]



  • @*0r:
    Ich hab jetzt ++i zu i++ geändert. Ich vermute aber, dass das nicht das ist was du meintest. (Der Effekt war auch nicht erkennbar, ich glaube aber so gehts besser.)

    Meinstest du sowas?

    for(i = 0; i < zeilenAnz; ++i)
        t[i] = malloc(spaltenAnz*sizeof(float));
    }
    

    Danke für eure Geduld, aber irgendwie sehe ich das Problem nicht, sorry.

    Grüße,
    Blue][ce



  • Blue][ce_ schrieb:

    Sie schlägt aber nicht an.

    Das ist auch eher eine Frage des Prinzips, denn es ist nicht garantiert, das malloc stets erfolgreich zurückkehrt. In manchen Situationen lässt sich durch die Prüfung des Rückgabewertes das Programm eventuell doch noch fortsetzen.

    Blue][ce_ schrieb:

    @*0r:
    Ich hab jetzt ++i zu i++ geändert. Ich vermute aber, dass das nicht das ist was du meintest.

    Das spielt hier keine Rolle.

    Blue][ce_ schrieb:

    Meinstest du sowas?

    for(i = 0; i < zeilenAnz; ++i)
        t[i] = malloc(spaltenAnz*sizeof(float));
    }
    

    Das ist die übliche Vorgehensweise, wenn man die Matrix zeilenweise abarbeiten/durchlaufen möchte. Es ist auch adersrum denkbar, dann werden die Spalten durchlaufen.

    Blue][ce_ schrieb:

    Danke für eure Geduld, aber irgendwie sehe ich das Problem nicht, sorry.

    Überdenke doch bitte noch einmal meinen obigen Beitrag (14:51:23 06.07.2009).



  • *0r schrieb:

    Das funktioniert zufällig, wenn sizeof(float) gleich sizeof(float*) ist. Probier das mal mit char** statt float**.

    Mit sizeof(float*) bekommst Du nur die größe eines Pointers auf float, und ein Pointer hat auf einem 32bit System immer 4byte, ein float auch daher klappt es bei Dir an dieser stelle, zufällig 😉
    Das wäre bei sizeof(char*) und sizeof(char) wieder etwas anderes, folgendes verdeutlicht es:

    printf("size of char %d, size of char* %d\n", sizeof(char), sizeof(char*)); // size of char 1, size of char* 4
    

    Jetzt probier es mal mit double, sizeof(double*) ist wieder 4 aber sizeof(double)? Richtig 8! d.h. heist wenn Du nun eine Matrix von double so erzeugst wie in Deinem Code kommt es in jedemfall zu einem SegFault!
    Merke: Ein Pointer auf jeden Typ sollte immer: sizeof(int) == sizeof(type)*

    *0r schrieb:

    spaltenAnz = 2;
    zeilenAnz = 3;
    float** t = malloc(spaltenAnz*sizeof(float*));
    
    for(i = 0; i < zeilenAnz/* !!! */; ++i)
        t[i] = malloc(sizeof(float));
    // Tipp: if i == 2 then RAM terr0r !
    

    Vorsicht sei auch hier geboten, habe die "Gefahrenstelle" mal mit einem Kommentar markiert. Denke aber mal das es sich hier nur um einen Flüchtigkeitsfehler handelt 😉

    Gut Schuß
    VuuRWerK 😉



  • VuuRWerK schrieb:

    ... ein float auch daher klappt es bei Dir an dieser stelle, zufällig 😉 ...

    *grins*
    Bei mir? Neee, bei dir! 🙂
    Meine Vorgehensweise funzt mit jedem Datentypen. Ersetzt man dagegen bei deiner Variante float durch char, dann gibts au weija uff!

    VuuRWerK schrieb:

    ...Jetzt probier es mal mit double, sizeof(double*) ist wieder 4 aber sizeof(double)? Richtig 8! d.h. heist wenn Du nun eine Matrix von double so erzeugst wie in Deinem Code kommt es in jedemfall zu einem SegFault!...

    Waaaahaaas?! Wie kommste denn auf das schmale Brett 😕
    Guck mal:

    int zeilen = 3, spalten = 2, i;
    double** matrix = malloc(zeilen*sizeof(double*));
    for(i=0;i<zeilen;i++)
        matrix[i]  = malloc(spalten*sizeof(double));
    

    Wo bitte ist da ein SegAutsch? 😕



  • VuuRWerK schrieb:

    Merke: Ein Pointer auf jeden Typ sollte immer: sizeof(int) == sizeof(type)*

    Das ist schlicht falsch.



  • *0r schrieb:

    Waaaahaaas?! Wie kommste denn auf das schmale Brett 😕

    #include <stdio.h>
    
    int main()
    {
      printf("size of char %d, size of char* %d\n", sizeof(char), sizeof(char*));
      printf("size of float %d, size of float* %d\n", sizeof(float), sizeof(float*));
      printf("size of double %d, size of double* %d\n", sizeof(double), sizeof(double*));
      return 0;
    }
    

    @Tim: Kannst Du Deine Aussage Begründen? Möglicherweise ist meine Aussage dahingehend "schwammig" das man es mit einem sizeof(int) vergleichen kann, ok mag doof aussehen. Aber 4Byte auf einem 32bit System sind nunmal 4Byte, sowohl ein int als auch ein jeder Pointer.

    Gut Schuß
    VuuRWerK 😉

    EDIT: @*0r: Hatte glaub grad 'nen Denkfehler. Na klar reicht ein sizeof(double*) in der ersten Dimension der Matrix, man will ja nur einen weiteren pointer auf double speichern und keinen ganzen double wert. Dann hhast natürlich recht, sry war mein Denkfehler. Die Aussage von Tim hätte ich dennoch gern näher erläutert 🙂



  • VuuRWerK schrieb:

    @Tim: Kannst Du Deine Aussage Begründen? Möglicherweise ist meine Aussage dahingehend "schwammig" das man es mit einem sizeof(int) vergleichen kann, ok mag doof aussehen. Aber 4Byte auf einem 32bit System sind nunmal 4Byte, sowohl ein int als auch ein jeder Pointer.

    Ich widerlege durch Gegenbeispiel: http://focus.ti.com/lit/ug/spru514c/spru514c.pdf (Seite 82)

    Ansonsten kannst du ja gerne mal deine Behauptung zu belegen versuchen 😉

    Edit: Vielleicht nicht ganz hundertprozentig sauber, da da wohl ein Vertipper im Manual vorliegt (pointers: 32Bit mit 0xFFFF als Maximum macht nicht viel Sinn), aber es sollte reichen deine Aussage zu überdenken 😉



  • VuuRWerK schrieb:

    #include <stdio.h>
    
    int main()
    {
      printf("size of char %d, size of char* %d\n", sizeof(char), sizeof(char*));
      printf("size of float %d, size of float* %d\n", sizeof(float), sizeof(float*));
      printf("size of double %d, size of double* %d\n", sizeof(double), sizeof(double*));
      return 0;
    }
    

    <irony>
    Na das zeigt natürlich alles 👍
    </irony>
    Das ist doch ein alter Hut, ich sehe da keinen SegFault.
    Meine Frage bezog sich natürlich auf meinen Code, da sehe ich ebenfalls keinen SegFault!



  • VuuRWerK schrieb:

    EDIT: @*0r: Hatte glaub grad 'nen Denkfehler. Na klar reicht ein sizeof(double*) in der ersten Dimension der Matrix, man will ja nur einen weiteren pointer auf double speichern und keinen ganzen double wert. Dann hhast natürlich recht, sry war mein Denkfehler.

    Oki doki!
    🙂



  • Tim schrieb:

    VuuRWerK schrieb:

    @Tim: Kannst Du Deine Aussage Begründen? Möglicherweise ist meine Aussage dahingehend "schwammig" das man es mit einem sizeof(int) vergleichen kann, ok mag doof aussehen. Aber 4Byte auf einem 32bit System sind nunmal 4Byte, sowohl ein int als auch ein jeder Pointer.

    Ich widerlege durch Gegenbeispiel: http://focus.ti.com/lit/ug/spru514c/spru514c.pdf (Seite 82)

    Ansonsten kannst du ja gerne mal deine Behauptung zu belegen versuchen 😉

    Edit: Vielleicht nicht ganz hundertprozentig sauber, da da wohl ein Vertipper im Manual vorliegt (pointers: 32Bit mit 0xFFFF als Maximum macht nicht viel Sinn), aber es sollte reichen deine Aussage zu überdenken 😉

    16bit 😕 Mein gcc gönnt mir in einem int 32, long ist zwar auch 32 aber das entspricht ja wieder der Tabelle. Komisch, ich bin immer von 4byte für ein int ausgegangen und da alle Adressen 32bit lang sind (auf einem 32bit System) ging ich immer von meine oben genannten Vergleich aus 😕

    Gut Schuß
    VuuRWerK 😉



  • Moin Jungs und Mädels! 🙂

    *0r schrieb:

    Selbst wenn zeilenAnz == spaltenAnz wäre, auf deine Elemente kannst du bei deiner Vorgehensweise nur so zugreifen:
    t[0][0], t[1][0], ... , t[spaltenAnz-1][0]

    Du meinst ich könnte so nur auf die erste Zeile zugreifen.

    Also statt so:

    for(i = 0; i < zeilenAnz; i++){
        t[i] = calloc(spaltenAnz, sizeof(float));
        if (t[i] == NULL){
    	printf("Auch boehse!");
        }
    }
    

    Dann so?

    for(i = 0; i < zeilenAnz*spaltenAnz; i++){
        t[i] = calloc(spaltenAnz, sizeof(float));
        if (t[i] == NULL){
    	printf("Auch boehse!");
        }
    }
    

    Greez,
    Blue][ce



  • Hab den zweiten Fehler nun auch gefunden.

    Ein free() an der falschen Stelle kann einfach viel Unheil anrichten!

    Funktionierende Funktion sieht nun so aus:

    floatMatrix MallocFloatMatrix(int zeilenAnz, int spaltenAnz) {
    	float** t = calloc(zeilenAnz,sizeof(float*));
    	if (t == NULL){
    		printf("Boehse!");
    		exit (1);
    	}
    	int i;
      	for(i = 0; i < zeilenAnz; i++){
        	t[i] = calloc(spaltenAnz, sizeof(float));
        	if (t[i] == NULL){
    			printf("Auch boehse!");
    			exit (1);
    		}
    	}
      return t;
    }
    

    Oder hab ich da immernoch schlummernde Zeitbomben drin?

    Auf jeden Fall vielen Dank für eure Hilfe! 🙂

    Grüße,
    Blue][ce



  • Das sieht schon ganz brauchbar aus. Optimal wäre es, wenn du bereits reservierten Speicher vor exit freigeben würdest.

    Gruß,
    *0r



  • Ah, gute Idee!

    floatMatrix MallocFloatMatrix(int zeilenAnz, int spaltenAnz) {
    	float** t = calloc(zeilenAnz,sizeof(float*));
    	if (t == NULL){
    		printf("Boehse!");
    		free(t);
    		exit (1);
    	}
    	int i;
      	for(i = 0; i < zeilenAnz; i++){
        	t[i] = calloc(spaltenAnz, sizeof(float));
        	if (t[i] == NULL){
    			printf("Auch boehse!");
    			free(t);
    			exit (1);
    		}
    	}
      return t;
    }
    

    Reicht es im zweiten Fall (der for-Schleife) nur t freizugeben? Oder muß ich t[i] separat freigeben?

    Blue][ce



  • Alle reserviertgen t[i].


Anmelden zum Antworten