Forum: PC-Programmierung Zugriffsverletzung C-Programm


von Albert (Gast)


Lesenswert?

Hallo
Ich mache in meinem Code irgendwo eine Zugriffsverletzung und weiß aber 
nicht wo.Ich hoffe ihr könnt mir dabei helfen.

H-File:
1
typedef struct {
2
  int temp;
3
  int druck;
4
  int day;
5
  int month;
6
  int year;
7
8
}weatherdata;
9
10
void appendWeatherData(weatherdata * data,int *sizeOfData);

C-File:
1
void appendWeatherData(weatherdata *data, int *sizeOfData)
2
{
3
  static int sizeOfDataSpace = 10;
4
5
  if (sizeOfDataSpace <= *sizeOfData) {
6
7
    if( (realloc(data, sizeof(weatherdata) * 10))!=NULL);
8
    {
9
      sizeOfDataSpace += 10;
10
    }
11
    
12
    
13
14
15
  }
16
17
  //irgendwas reinschreiben
18
  if (*sizeOfData < sizeOfDataSpace) {
19
20
    
21
22
    data[*sizeOfData].day = *sizeOfData;
23
    data[*sizeOfData].druck = *sizeOfData;
24
    data[*sizeOfData].month = *sizeOfData;
25
    data[*sizeOfData].temp = *sizeOfData;
26
    data[*sizeOfData].year = *sizeOfData;
27
    
28
    *sizeOfData = *sizeOfData + 1;
29
    
30
  }
31
32
  
33
  
34
}

Main-File:
1
int main()
2
{
3
  int size = 0;
4
  weatherdata *data;
5
6
  data = (weatherdata*)calloc(10 ,sizeof(weatherdata));
7
8
  for (int i = 0; i < 20; i++)
9
  {
10
    appendWeatherData(data, &size);
11
12
13
  }
14
15
  for (int i = 0; i < size-1; i++)
16
  {
17
    if (data != NULL) {
18
      printf("Daten: %d -->%d %d %d Temp:%d Druck%d \n",i+1 ,data[i].day,data[i].month,data[i].year, data[i].temp, data[i].druck);
19
    }
20
    
21
    
22
    
23
24
  }
25
  
26
  if (data != NULL) {
27
28
    free(data);
29
  }
30
  
31
32
33
    return 0;
34
}

--

Die Tags werden natürlich ohne Leerzeichen geschrieben. Wenn man sie 
aber so in den Text reinschreibt, werden sie ausgewertet und dann sind 
sie für Dich nicht sichtbar ...

Sieh Dir mal den Hinweistext an, der hier oberhalb der Editbox steht.

-rufus

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

Du benutzt realloc falsch.

Du musst die Größe des gesamten benötigten BEreichs angeben, nicht nur 
die vom neuen.

Und es wird die Adresse von diesem Bereich zurück gegeben.
Das kann eine andere Adresse als vorher sein.

PS. Die Code-Tags haben i.A. keine Leerzeichen

: Bearbeitet durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Albert schrieb:
> if( (realloc(data, sizeof(weatherdata) * 10))!=NULL);

Das geht ganz gewaltig in die Hose, denn Du schmeißt den Rückgabewert 
von realloc weg ...

von Rolf M. (rmagnus)


Lesenswert?

Albert schrieb:
> C-File:
> [ c ]
> void appendWeatherData(weatherdata *data, int *sizeOfData)
> {
>   static int sizeOfDataSpace = 10;
>
>   if (sizeOfDataSpace <= *sizeOfData) {
>
>     if( (realloc(data, sizeof(weatherdata) * 10))!=NULL);

Wie Dirk schon schreibt, musst du den Rückgabewert nicht nur prüfen, 
sondern dir auch merken. Da steht die neue Adresse des reallokierten 
Speichers drin. Die verwirfst du aber und nutzt die alte, möglicherweise 
nicht mehr gültige Adresse weiter.
Abgesehen davon ist das Semikolon am Ende der Zeile falsch.

> Main-File:
> [ c ]
> int main()
> {
>   int size = 0;
>   weatherdata *data;
>
>   data = (weatherdata*)calloc(10 ,sizeof(weatherdata));

Den Cast solltest du weglassen. Der ist überflüssig und kann sogar 
Fehler verdecken.

Ich finde den Code generell recht umständlich und unnötig schwer 
verständlich. Aber das ist denke ich für den Anfang normal.

Dirk B. schrieb:
> PS. Die Code-Tags haben i.A. keine Leerzeichen

Wie man übrigens auch direkt über dem Eingabefeld bei den 
Formatierungsregeln sehen kann. Es schadet auch nicht, vor dem Absenden 
sich mal in der Vorschau anzusehen, ob alles passt.

von Albert (Gast)


Lesenswert?

Sorry für die Tags.
Erstmal danke für die schnelle Hilfe.
Ich hab das nun geändert
1
if (sizeOfDataSpace <= *sizeOfData) {
2
3
    data = realloc(data, sizeof(weatherdata) * (sizeOfDataSpace+10));
4
5
    if (data != NULL) {
6
7
      sizeOfDataSpace += 10;
8
    }

Jetzt läuft es bis zum free(data) durch und da bekomm ich eine 
Zugriffsverletzung. Woran liegt das ?
Wie läuft das eigentlich genau mit realloc?
Werden die vorhanden Daten kopiert und ein neuer Speicher daran gehängt?
Wird der alte Speicher automatisch freigegeben?

von Dirk B. (dirkb2)


Lesenswert?

Albert schrieb:
> Jetzt läuft es bis zum free(data) durch und da bekomm ich eine
> Zugriffsverletzung. Woran liegt das ?

Ich denke, dass du das data nicht richtig aus appendWeatherData an main 
zurück gibst.

Dazu brauchst du einen Doppelzeiger oder einen anderen Rückgabetyp als 
void.

Albert schrieb:
> Wie läuft das eigentlich genau mit realloc?

Woher kennst du denn realloc?
Da muss doch irgendwas erklärt worden sein.

realloc ist eine Funktion aus der C-Standardbibliothek.
Und die sind außerordentlich gut dokumentiert.

Z.B. http://www.cplusplus.com/reference/cstdlib/realloc/?kw=realloc

Da klären sich auch die andeen Fragen.


Aber wenn du beim realloc-Aufruf data gleich wieder überschreibst, dann 
gehen dir im Fehlerfall (NULL) die Daten verloren.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Albert schrieb:
> data = realloc(data, sizeof(weatherdata) * (sizeOfDataSpace+10));

Das ist zwar besser, aber immer noch ungeschickt.

Stell' Dir folgende Situation vor:

Vor dem Aufruf von realloc zeigt data auf Speicher, den Du mühsam 
angefordert und gefüllt hast.

Nun willst Du mehr Speicher anfordern als verfügbar ist, was realloc 
mit dem Zurückgeben von NULL quittiert.

Und was ist mit den Daten, auf die vorher data zeigte?

Die sind immer noch da. Aber Du hast mit der Zuweisung des Ergebnisses 
von realloc an data weggeworfen, wo die Daten sind, d.h. Du kannst 
den Speicher auch nicht mehr freigeben ...

Fazit: Niemals den Rückgabewert von realloc unmittelbar dem gleichen 
Pointer zuweisen, der als erstes Argument übergeben wird. Nimm einen 
Hilfspointer, prüfe den und erst wenn er nicht NULL ist, weist Du diesen 
neuen Pointer dem jetz ungültigen Pointer data zu. Ist er aber NULL, 
ist data nach wie vor gültig, und Du hast die Chance, irgendwas 
sinnvolles damit anzufangen.

von size (Gast)


Lesenswert?

lass dir mal in appenddata zu beginn deine datasize vor dem if ausgeben

von Albert (Gast)


Lesenswert?

Das mit den Hilfs-Pointer macht sinn. Hab das geändert. Danke
Das mit dem datasize ausgeben versteh ich nicht. Da steht immer die 
aktuelle Anzahle der Datensätze drin. Versteh nicht was es bringen soll.
Ich hab jetzt die Funktion geändert. Nun gibt Sie einen weatherData 
Pointer zurück. Jetzt funktioniert auch das free.
Find es trotzdem komisch das es vorher nicht funktioniert hat. Immerhin 
kann ich ja vor dem free noch auf alle Daten zugreifen ohne eine 
Zugriffsverletzung.

von Andreas E. (hismastersvoice)


Lesenswert?

Das hat vorher funktioniert, da main noch auf den alten Speicher zeigte, 
den noch nichts überschrieben hat.
Das free ging nicht, weil malloc den Speicher schon zurück genommen hat. 
Die Daten darin existieren aber noch.
Lass mal in Deinem alten Code appendWeatherData irgendein Feld in dem 
reallocierten data ändern und lies das dann in main aus. Dann solltest 
Du es sehen!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.