Komisches Pointerverhalten und Fehlermeldung bei free
-
Hier handelt es sich um ein Codebeispiel das ich modifiziert habe. Früher gab es eine *hilf Pointer der statt dem *memptr raufgezählt wurde. Zum Schluß wurde dann über eine schleife mit printf die Inhalte der Pointervariablen memptr ausgelesen.
Meine Aufgebenstellung für mich war es das alles nur mit einem Pointer hinzubekommen.
Erwarten tue ich 2 1 0.
Bekommen tue ich 2 rießige Zahlen und eine 0. Die 0 passt wenigstens schon malBeim Debuggen ( und nicht beim normalen ausführen ) fliegt er auch beim free raus ...
No source available for "ntdll!TpWaitForAlpcCompletion() at 0x77c80575 warum auch immer. Böse Pointer
Ich Code dient nur Testzwecken./* bspl0099.c */ #include <stdlib.h> #include <stdio.h> #define MAX_ZAHL 2 int main() { double *memptr,*hilf; int i; memptr = (double *) malloc(MAX_ZAHL * sizeof(double)); //hilf = memptr; if(memptr == NULL) { printf("\nNicht genuegend Speicher!"); exit(1); } printf("\nSpeicher fuer %i double-Werte ok!\n", MAX_ZAHL); for(i=0; i<=MAX_ZAHL; i++) { *memptr=i; memptr = memptr+1; } memptr--; for(i=3; *memptr != 0; i) { printf(" %f",memptr[i]); memptr--; } printf(" %f",memptr[i]); free(memptr); printf("\nSpeicherplatz wieder freigegeben!"); return 0; }
-
Du veränderst den memptr und wunderst dich, warum er beim free() crasht?!
Und deine Ausgabeschleife ist auch vermurkst, daher erhältst du andere Zahlen (als erwartet), weil du auf falsche Speicherbereiche zugreifst (UB).
Nur mit einem Zeiger geht es ganz einfach, indem du nicht dem memptr veränderst, sondern so wie in deiner ersten Schleife einen Schleifenzähler benutzt und dann aber mittels des Index-Operators auf die Inhalte zugreifst:
for(i=0; i<MAX_ZAHL; i++) // hier war auch <= falsch! memptr[i] = i;
Und nun einfach noch die Ausgabeschleife so anpassen, daß sie wie diese funktioniert...
-
for(i=3; *memptr != 0; i) {
Was soll diese unsinnige Zeile bewirken?
Hier ist alles falsch.
-
thx,
die Schleife war ein Versuch ob das überhaupt geht. Ja es geht .. Abbruchbedienung wird über eine Pointervariable geregelt und nicht über eine Zählervariable ...
while(Bedienung) wäre aber sicher vernünftiger gewesen.Ich probier halt alles aus
warum darf ich einen Pointer nicht free"en" wenn ich ihn 3 mal raufzähle und 3 mal runterzähle ? Zum Schluss zeigt er auf die gleiche Stelle wie am Anfang oder ist das free"en" von Pointern die schon mal rauf/ runtergezählt worden ein Unding in c ?
Index Operator versuche ich sogut es geht zu vermeiden da ich mir die Schreibweise mit Pointern angewöhnen will um Code der nicht von mir stammt besser lesen zu können.
-
Bullz schrieb:
Zum Schluss zeigt er auf die gleiche Stelle wie am Anfang oder ist das free"en" von Pointern die schon mal rauf/ runtergezählt worden ein Unding in c ?
Der Compiler hat immer recht.
Wenn der Code bei free abbricht, dann entweder weil du zuvor schon mal free auf dieselbe Adresse angewendet hast oder zuvor kein malloc/calloc/realloc auf die Adresse angewendet hast.
Der Compiler hat immer recht, d.h. du hast unrecht.
Vergleiche mit Gleitkommazahlen (==,>=,<=) sind kritisch. Bei Schleifen immer zu vermeiden, um nicht in eine Endlosschleife zu gelangen.
-
Bullz schrieb:
warum darf ich einen Pointer nicht free"en" wenn ich ihn 3 mal raufzähle und 3 mal runterzähle ? Zum Schluss zeigt er auf die gleiche Stelle wie am Anfang oder ist das free"en" von Pointern die schon mal rauf/ runtergezählt worden ein Unding in c ?
Du darfst das:
int main(void) { char *ptr = malloc(1); ptr += 3; ptr -= 3; free(ptr); }
Ich empfehle dir, es nicht zu tun, weil du dir so schnell in den Fuß schießt.
Der Fehler liegt nicht beim free.
Du greifst auf nicht reservierten Speicher zu: zB memptr[2] in Zeilen 19 und 26.
-
Also danke für die Hilfe. Bin mal soweit gekommen dass ich das Ergebnis bekomme habe was ich wollte. Nur beim free schmiert er mir beim Debuggen immer ab und ich verstehe nicht warum ... muss compiler Fehler sein
joke
Ich bekomme eine Speicheradresse mit Platz für 3 Int also 12 Byte
0xae1850
0xae1854
0xae1858diese zählt er 2 mal wieder runter
0xae1854
0xae1850und dann probiert er ein free auf 0xae1850. Peng ...
/* bspl0099.c */ #include <stdlib.h> #include <stdio.h> #define MAX_ZAHL 2 int main() { int *memptr; int i; memptr = (int *) malloc(MAX_ZAHL * sizeof(int) + 1); if(memptr == NULL) { printf("\nNicht genuegend Speicher!"); exit(1); } printf("\nSpeicher fuer %i double-Werte ok!\n", MAX_ZAHL + 1); for(i=0; i<=MAX_ZAHL; i++) { *memptr=i; if(i ==2) continue; memptr = memptr+1; } i--; while(*memptr != 0) { printf(" %d",*memptr); memptr--; } printf(" %d",*memptr); // memptr[2] = 2 memptr[1] = 1 memptr[0] = 0 free(memptr); printf("\nSpeicherplatz wieder freigegeben!"); return 0; }
-
Du bist ein Noob.
Du ignorierst du Vorschläge, die gemacht werden und benutzt deinen Unsinnscode weiterhin.
Es sollte sich hier niemand mehr um deine 'Fragen' kümmern.
-
Bullz schrieb:
Ich bekomme eine Speicheradresse mit Platz für 3 Int also 12 Byte
Wo denn?
-
Wutz schrieb:
Du bist ein Noob.
Stimmt ;), deswegen lerne ich es. Ich weiß das der Code eine Katastrophe ist, aber ich hab durch diesen Mist viel gelernt...
nachdem ich das mit dem View Memory rausgefunden hatte, war es viel leichter einen Überblick zu halten. wie oben bei meinem Beispiel 2*4 + 1 ist halt nicht 12 ;). Werde jetzt aber eine Version erstellen wo ich den Pointer nicht raufzähle
DirkB schrieb:
Bullz schrieb:
Ich bekomme eine Speicheradresse mit Platz für 3 Int also 12 Byte
Wo denn?
ja ich weiß ... wenigstens weiß ich das free der Punkt ist wo man nachsehen kann ob man sauber gearbeitet hat oder man Blödsinn gebaut hat.
Das einzige was mich jetzt noch vor ein Problem stellt ist das ich selbst mit view Memory noch nicht " Idiotensicher " erkenne kann ob ich innerhalb meines Speicherbereichs gearbeitet habe... gibt da eine Lösungen außer externe Software / Addons ?
Version ohne Pointerspielchen. So hat man viel weniger Bauchweh
aber ab und zu muss man sich die Finger verbrennen um was dazu zulernen.
#define MAX_ZAHL 2 int main() { int *memptr; int i; memptr = (int *) malloc((MAX_ZAHL + 1)* sizeof(int) ); if(memptr == NULL) { printf("\nNicht genuegend Speicher!"); exit(1); } printf("\nSpeicher fuer %i double-Werte ok!\n", MAX_ZAHL + 1); for(i=0; i<=MAX_ZAHL; i++) { memptr[i]=i; if(i ==2) break; } while(memptr[i] != 0) { printf(" %d",memptr[i]); i--; } printf(" %d",memptr[i]); free(memptr); printf("\nSpeicherplatz wieder freigegeben!"); return 0; }
-
Definiere MAX_ZAHL gleich mit dem richtigen Wert und verzichte auf das +1 und das <=
-
Schade,das es hier keinen Danke Knopf gibt. Mach ich danke.
-
Bullz schrieb:
Das einzige was mich jetzt noch vor ein Problem stellt ist das ich selbst mit view Memory noch nicht " Idiotensicher " erkenne kann ob ich innerhalb meines Speicherbereichs gearbeitet habe... gibt da eine Lösungen außer externe Software / Addons ?
Ja. Compiler wie GCC und Clang bieten da z.B. den AddressSanitizer an. Einfach mit -fsanitize=address kompilieren (und linken) und bei fehlerhafter Nutzung des Speichers gibt dein Programm eine Fehlermeldung mit Backtrace usw. aus. Im Gegensatz zu Tools wie Valgrind kosten die Checks auch nicht so übel Performance.
Gibt auch noch andere Sanitize-Optionen. Undefined z.B. oder Thread. Brauchst halt nur einen aktuellen GCC oder Clang.