[gelöst] Dynamische Speicherallokation mit calloc()



  • Siegfried1 schrieb:

    Ich frage mich nur, was ich daran falsch machen könnte. Der folgende Zugriff führt zum Speicherzugriffsfehler.

    xyz->something[0] = 0.1;
    

    Tja, fragt sich überhaupt erst mal was my_type denn für ein Type ist. Ansonsten hat Janjan alles gesagt. Wenn beim allokieren ein Fehler (out of memory etc.) auftritt, dann wird 0 zurückgegeben. Ist dies nicht der Fall, dann wurde auch deine gewünschte Speichergröße allokiert.
    Alles andere wäre ja auch Unfug ...



  • Nur zur Info,
    ich weiß zwar nicht ob es das Problem ist,
    aber wenn calloc einen Pointer != NULL liefert bedeutet daß nur,
    daß der Speicher virtuell reserviert werden konnte.

    Ob hinter dem Pointer nun auch echtes RAM steckt oder nicht ist
    soo ohne Weiteres nicht klar.

    Bei modernen Betriebsystemen bleibt es erst mal nur bei der virtuellen Reservierung.

    Das kann man einfach prüfen indem man mal die Zeit misst für
    ein:

    calloc (1000 * 1000 * 100);
    

    Viel Erfolg, Gruß Frank



  • Frank Erdorf schrieb:

    Das kann man einfach prüfen indem man mal die Zeit misst für
    ein:

    calloc (1000 * 1000 * 100);
    

    das sagt erstmal nix aus... ob der virtuelle speicher auf realen ram zeigt spielt erstmal keine rolle (so weit ich weiß), wird erst spannend wenns dann auf die festplatte wechselt, aber dann ist dein system idr. eh so langsam dass nur noch die reset taste hilft^^



  • Hallo zusammen

    Hintergrund ist das 'Feature' Overcommit.

    Hierbei der gibt der VMM mehr virtuellen Speicher aus,
    als er real (RAM + SWAP) zur Verfügung hat.

    d.h. man kann einen scheinbar gültigen Pointer beim malloc erhalten,
    bekommt dann doch beim späteren Zugriff einen SEGMENTATION FAULT.

    Ob das hier zutrifft ist, mit den bisherigen Informationen, unwarscheinlich,
    ich wollte es dennoch erwähnt haben ...

    also:
    wenn pointer != NULL dann kein SEGMENTATION FAULT beim späteren Zugriff
    gilt nicht immer.

    Gruß Frank



  • also so hab ich das noch nie betrachtet ist mir auch noch nie untergekommen aber schön das es fehler gibt die ich nicht mit einem if() abfangen kann, ist aber implementations abhängig und daher gehe ich davon aus dass mir ein m/r/c ein gültigen pointer liefert, mit dem ich auch arbeiten kann, denke so stehts auch im standard...



  • Danke für die vielen Rückmeldungen!!!

    Sorry, dass ich nicht meinen gesamten Code gepostet hatte; Ich wollte das Problem möglichst einfach und kompakt darstellen.

    Mein gesamtes Programm ist ziemlich umfangreich und sehr Speicherlastig. Das folgende Testprogramm zeigt letztendlich den Ausschnitt, der Probleme macht.

    #include <stdio.h>
    #include <stdlib.h>
    
    struct my_struct {
        float *something;
    };
    
    void allocation(struct my_struct *xyz)
    {    
        if(xyz->something == NULL)
        {
            xyz->something = (float *) calloc(12*10*20, sizeof(float));
    
            if(xyz->something == NULL)
            {
                printf("Fehlermeldung\n");
                return;
            }       
        }
        xyz->something[0] = 0.1; // <-- Speicherzugriffsfehler --> //
    }
    
    int main()
    {
        struct my_struct *xyz;
        xyz = (struct my_struct *) malloc(sizeof(struct my_struct));
        if(xyz == NULL)
        {
    	    printf("Fehlermdldung\n");
    	    return 1;
        }
        allocation(xyz);
        return 0;
    }
    

    In diesem Testprogramm tritt allerdings dieser Speicherzugriffsfehler NICHT auf!

    Mein eigentliches Programm ist sehr Hauptspeicherlastig. Es liest anfangs eine 245MiB große Textdatei ein, welche nur aus Fließkommazahlen besteht (werden als float eingelesen). Dann dachte ich, dass dies vielleicht genau das Problem ist, denn mein RAM hat nur 2GB. Aber eigentlich müsste mein Mandriva Linux bei Speichermangel automatisch auf die Festplatte auslagern.

    Morgen werde ich mir das nochmal genauer anschauen. Danke euch Allen!!

    Siegfried1



  • In diesem Beispiel hast du zumindest mal den Fehler, dass die Struktur für die du in main() speicher reservierst nicht initialisiert wird. Somit kann der member something durch != NULL sein. Dadurch würde a) dein realloc()-Block in allocation() und b) der Zugriff auf something ins Nirvana gehen. Klar?

    Ansonsten mal Werbung in eigener Sache: http://www.c-plusplus.net/forum/viewtopic.php?t=206606



  • Danke für den Link. Wird wohl als schlechter Stil bezeichnet, was ich da geschrieben habe. Und free() habe ich auch vergessen 🙄
    Allerdings ist mir nicht ganz klar, was du mit folgendem Satz meinst:

    Tim schrieb:

    In diesem Beispiel hast du zumindest mal den Fehler, dass die Struktur für die du in main() speicher reservierst nicht initialisiert wird.



  • Du initialisierst xyz->something nicht. Es hat einen undefinierten Wert. Dieser undefinierte Wert ist höchstwahrscheinlich NICHT null, deswegen wird dein calloc() nie ausgeführt.



  • Danke Danke!!! Problem gelöst :p



  • Hab so ein ähnliches Problem und suche eine Lösung.
    Wieso ist xyz nicht initialisiert?
    xyz ist doch ein Pointer und wird mit dem Zeiger der von Calloc zurückgeliefert wird initialisiert, bzw. mit NULL.

    Ist es für calloc notwendig, dass xyz bereits woanders hinschaut?
    MfG Toe



  • Es geht nicht um xyz sondern um xyz->something und ist auch kein Problem von calloc.

    Das Problem tritt in Zeile 10 auf.
    In xyz->something kann irgendetwas stehen was != NULL ist. Denn xyz->something wurde vorher noch kein Wert zugewiesen.
    Dann wird der if-Zweig mit calloc nicht ausgeführt.
    xyz->something zeigt dann irgendwo hin (ins Nirvana 🙂 )

    In Zeile 20 wird aber trotzdem (mit xyz->something[0] = 0.1; ) darauf zugegriffen.

    Ein xyz->something = NULL; zwischen Zeile 31 und 32 behebt den Fehler.



  • Dem Beitragstitel entsprechend ersetze

    xyz = (struct my_struct *) malloc(sizeof(struct my_struct));
    

    durch

    xyz = calloc(1,sizeof*xyz);
    

    und du hast die Probleme nicht mehr weil alles initialisiert ist und somit auch something gleich NULL ist.



  • aha, jetzt seh ichs auch. Danke für die Erläuterung.
    Habe mittlerweile mein Problem auch in den Griff bekommen.
    Hab vergessen ein & bei einem Parameter wo ich den Pointer direkt übergeben wollte mitzugeben. Mein Programm schnurrt jetzt und ist auch lang genug um den Professor zufrieden zu stellen.
    Hoffentlich! Wünsche noch einen guten Rutsch.


Anmelden zum Antworten