So richtig habe ich realloc() wohl noch nicht begriffen...



  • Hi(gh)!

    ...anders kann ich mir den Speicherzugriffsfehler mit diesem Code hier nicht erklären:

      Klimadatensatz* Gesamtdatei;
      unsigned int i=0;
        
      Gesamtdatei = malloc(sizeof(Klimadatensatz));
      FILE* fp;
      fp = fopen("wikipedia_klimadaten.dat", "rb"); // Datei wird als Binärdatei geöffnet!
      if (!fp)
      {  
        printf("\nDatei kann nicht geöffnet werden!");
        return false;
      }
      while (fread(&Gesamtdatei[i], sizeof(Klimadatensatz), 1, fp) == 1 )
      {
        if (i > 0)
          Gesamtdatei=realloc(Gesamtdatei, sizeof(Klimadatensatz));
        i++;  
      }
    
    

    Was mache ich falsch?

    Bis bald im Khyberspace!

    Yadgar



  • Realloc erwartet als zweiten Parameter die neue Größe, nicht die Größe, um die der Speicherbereich vergrößert werden soll. Außerdem kann realloc auch Null zurück liefern, dann hast du deine bisherigen Daten verloren und noch ein Speicherleck. Also den Rückgabewert in einer anderen Variablen speichern und nur dann Gesamtdateizuweisen, wenn sie ungleich 0 ist. Wenn 0 -> Abbruch.



  • @yahendrik sagte in So richtig habe ich realloc() wohl noch nicht begriffen...:

    Realloc erwartet als zweiten Parameter die neue Größe, nicht die Größe, um die der Speicherbereich vergrößert werden soll. Außerdem kann realloc auch Null zurück liefern, dann hast du deine bisherigen Daten verloren und noch ein Speicherleck. Also den Rückgabewert in einer anderen Variablen speichern und nur dann Gesamtdateizuweisen, wenn sie ungleich 0 ist. Wenn 0 -> Abbruch.

    Das hier:

      Klimadatensatz* Gesamtdatei;
      Klimadatensatz* pkd;
      unsigned int i=0;
        
      Gesamtdatei = malloc(sizeof(Klimadatensatz));
      FILE* fp;
      fp = fopen("wikipedia_klimadaten.dat", "rb"); // Datei wird als Binärdatei geöffnet!
      if (!fp)
      {  
        printf("\nDatei kann nicht geöffnet werden!");
        return 1;
      }
      while (fread(&Gesamtdatei[i], sizeof(Klimadatensatz), 1, fp) == 1 )
      {
        i++;
        pkd=realloc(Gesamtdatei, sizeof(Klimadatensatz)*i);
         if (!pkd)
           return 1;
         else
           Gesamtdatei = pkd;
      }
    
    

    funktioniert leider auch nicht, ich bekomme nach wie vor den Speicherzugriffsfehler!



  • unsigned int i=0;
    ...
    while(...)
    ++i;
    im ersten Druchlauf:
    -> Klimadatensatz wird nicht vergrößert (1*sizeof(...))
    


  • @yahendrik sagte in So richtig habe ich realloc() wohl noch nicht begriffen...:

    unsigned int i=0;
    ...
    while(...)
    ++i;
    im ersten Druchlauf:
    -> Klimadatensatz wird nicht vergrößert (1*sizeof(...))
    

    pkd=realloc(Gesamtdatei, sizeof(Klimadatensatz)*(i+1));

    ...so ist es richtig! Danke für den Tipp!



  • Du kannst übrigens statt malloc auch realloc mit NULL bzw. dem auf NULL gesetzten Zeiger aufrufen.



  • Lerne am besten erstmal einen Debugger zu bedienen, damit du nachvollziehen kannst wo diese Zugriffsfehler genau passieren. Dadurch erklärt er sich ziemlich sicher von selbst.



  • @tggc sagte in So richtig habe ich realloc() wohl noch nicht begriffen...:

    Lerne am besten erstmal einen Debugger zu bedienen, damit du nachvollziehen kannst wo diese Zugriffsfehler genau passieren. Dadurch erklärt er sich ziemlich sicher von selbst.

    Das ist ja noch mal eine ganze Computersprache für sich...



  • Aber Programmieren ohne Debugger ist wie Rechnen ohne Taschenrechner. Und jede (vernünftige) IDE hat doch einen Debugger eingebaut.



  • @Yadgar
    Wenn du nicht mit einem Debugger arbeiten willst (manchmal kannst du es vielleicht auch einfach nicht), dann bau dir doch einfach Programmausgaben ein, so im Sinne von "Programm gestartet", "realloc aufgerufen mit Rückgabe %p" usw.

    Damit kannst du auch sehr genau sehen, wo das Programm stehen bleibt oder abstürzt und du musst nicht aufwändig mit dem Debugger danach suchen.



  • @Wade1234 sagte in So richtig habe ich realloc() wohl noch nicht begriffen...:

    @Yadgar
    Wenn du nicht mit einem Debugger arbeiten willst (manchmal kannst du es vielleicht auch einfach nicht), dann bau dir doch einfach Programmausgaben ein, so im Sinne von "Programm gestartet", "realloc aufgerufen mit Rückgabe %p" usw.

    Damit kannst du auch sehr genau sehen, wo das Programm stehen bleibt oder abstürzt und du musst nicht aufwändig mit dem Debugger danach suchen.

    Nehme aber stderr statt stdout. stderr ist ungepuffert und erhöht die Wahrscheinlichkeit dir die richtige Stelle anzuzeigen sehr. Bei stdout kann es passieren das die Ausgabeoperation zwar schon ausgeführt wurde, am Bildschirm aber noch nichts zu sehen ist. Der Text steht dann im Ausgabepuffer der wiederum beim Programmabsturz einfach gelöscht wird. Was intern passiert ist allerdings z.B. Betriebsystemabhängig. Bei stderr kann dies auch passieren, die Wahrscheinlichkeit ist aber geringer da flush nach jeder Ausgabeoperation aufgerufen wird.