Wie gibt man den eines Structmembers wieder frei?
-
Folgender Code:
struct element; typedef struct element *zeiger; struct element { char *str; } zeiger hilf; hilf = (zeiger) malloc(sizeof (struct element)); hilf->str = (char*) malloc(15 * sizeof (char)); hilf->str = "Mein Text"; /* Nun geben wir den Speicher des Structs wieder frei: */ free(&(hilf->str)); // Zuerst den Speicher des Char Arrays auf das der Zeiger des Structs zeigt free(hilf); // Und dann das Struct selbst.
Das Problem ist nun, das er free(&(hilf->str)); nicht freigeben kann, da es anscheinend noch allokiert ist.
Frage:
Muß ich das Char Array erst auf einen char* Pointer sichern und dann
den Zeiger hilf->str auf NULL setzen, damit das Char Array nicht mehr vom Struct allokiert ist und ich es löschen kann?Also so:
// Lege Hilfszeiger an: char *ptr; ptr = &(hilf->str); // Dereferenziere hilf->str auf NULL hilf->str = 0; // Gebe Speicher frei free(hilf); free(ptr);
-
Anfänger 4 schrieb:
hilf->str = (char*) malloc(15 * sizeof (char)); hilf->str = "Mein Text"; free(&(hilf->str)); // Zuerst den Speicher des Char Arrays auf das der Zeiger des Structs zeigt
Das Problem ist nun, das er free(&(hilf->str)); nicht freigeben kann, da es anscheinend noch allokiert ist.
Nein, er kann es nicht freigeben, weil hilf->str nicht auf einen mit malloc angeforderten Speicherblock zeigt, sondern auf das Stringliteral "Mein Text". Du wolltest wahrscheinlich den String in hilf->str kopieren, das geht so:
strcpy(hilf->str, "Mein Text");
-
Bashar schrieb:
Nein, er kann es nicht freigeben, weil hilf->str nicht auf einen mit malloc angeforderten Speicherblock zeigt, sondern auf das Stringliteral "Mein Text". Du wolltest wahrscheinlich den String in hilf->str kopieren, das geht so:
strcpy(hilf->str, "Mein Text");
Besten Dank, habe das jetzt korrigiert, aber valgrind meldet mir immer noch, daß er den Speicher nicht freigeben kann.
Da muß also noch wo anders ein Fehler drinstecken.
-
Hier nochmal das komplette Programm:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { struct element; typedef struct element *zeiger; struct element { int i; char *str; }; zeiger hilf; hilf = (zeiger) malloc(sizeof (struct element)); hilf->str = (char*) malloc(15 * sizeof (char)); hilf->str = "Mein Text"; /* Nun geben wir den Speicher des Structs wieder frei: */ printf("Pointer von Zeiger hilf = %p\n", &hilf); printf("Pointer von Inhalt auf den Zeiger hilf verweist = %p\n", hilf); printf("Pointer von Char str Array, Member von struct hilf: hilf->str = %p\n", &(hilf->str)); free(&(hilf->str)); // Zuerst den Speicher des Char Arrays auf das der Zeiger des Structs zeigt freigeben free(hilf); // Und dann das Struct selbst. return 0; }
Und hier die Ausgabe von valgrind:
valgrind --leak-check=full ./freetest ==5485== Memcheck, a memory error detector ==5485== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al. ==5485== Using Valgrind-3.5.0-Debian and LibVEX; rerun with -h for copyright info ==5485== Command: ./freetest ==5485== Pointer von Zeiger hilf = 0x7ff000188 Pointer von Inhalt auf den Zeiger hilf verweist = 0x519a040 Pointer von Char str Array, Member von struct hilf: hilf->str = 0x519a048 ==5485== Invalid free() / delete / delete[] ==5485== at 0x4C24D68: free (vg_replace_malloc.c:325) ==5485== by 0x400647: main (in ~/freetest) ==5485== Address 0x519a048 is 8 bytes inside a block of size 16 alloc'd ==5485== at 0x4C25153: malloc (vg_replace_malloc.c:195) ==5485== by 0x4005C6: main (in ~/freetest) ==5485== ==5485== ==5485== HEAP SUMMARY: ==5485== in use at exit: 15 bytes in 1 blocks ==5485== total heap usage: 2 allocs, 2 frees, 31 bytes allocated ==5485== ==5485== 15 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==5485== at 0x4C25153: malloc (vg_replace_malloc.c:195) ==5485== by 0x4005D8: main (in ~/freetest) ==5485== ==5485== LEAK SUMMARY: ==5485== definitely lost: 15 bytes in 1 blocks ==5485== indirectly lost: 0 bytes in 0 blocks ==5485== possibly lost: 0 bytes in 0 blocks ==5485== still reachable: 0 bytes in 0 blocks ==5485== suppressed: 0 bytes in 0 blocks ==5485== ==5485== For counts of detected and suppressed errors, rerun with: -v ==5485== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 4 from 4)
Die Zeiger sind hier 8 Byte groß, da 64 Bit OS.
-
Ah richtig, da ist noch ein Fehler, den hab ich gar nicht gleich gesehen:
free(&(hilf->str)); /* die inneren Klammern sind überflüssig übrigens */
sollte
free(hilf->str);
heißen. Sonst übergibst du ja die Adresse des Strukturelements hilf->str. Nun hat deine Struktur nur ein Element, d.h. die Adresse ist (numerisch) gleich der Adresse von hilf, du würdest also zweimal den gleichen Block freigeben.
edit: In deinem neuen Posting ist es nicht mehr das erste Element, also ist die Adresse von hilf->str gar kein Zeiger mehr, der von malloc geliefert wurde. valgrind sagt hier "Address 0x519a048 is 8 bytes inside a block of size 16 alloc'd " d.h. &hilf->str ist 8 Bytes weiter als hilf. Passt, wegen 64Bit.
-
Bashar schrieb:
Ah richtig, da ist noch ein Fehler, den hab ich gar nicht gleich gesehen:
free(&(hilf->str)); /* die inneren Klammern sind überflüssig übrigens */
sollte
free(hilf->str);
heißen. Sonst übergibst du ja die Adresse des Strukturelements hilf->str. Nun hat deine Struktur nur ein Element, d.h. die Adresse ist (numerisch) gleich der Adresse von hilf, du würdest also zweimal den gleichen Block freigeben.
Ok, ich habe free(hilf->str); jetzt entsprechend geändert und das Struct um ein int member erweitert, wie oben im letzten Programmcode.
Aber Valgrind meldet mir immer noch, daß ich Speicher verlieren würde.
-
Aber nicht in dem Programm.
-
Bashar schrieb:
Aber nicht in dem Programm.
Doch:
[cpp]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>int main()
{
struct element;
typedef struct element *zeiger;struct element
{
int i;
char *str;
};zeiger hilf;
hilf = (zeiger) malloc(sizeof (struct element));
hilf->str = (char*) malloc(15 * sizeof (char));
hilf->str = "Mein Text";/* Nun geben wir den Speicher des Structs wieder frei: */
printf("Pointer von Zeiger hilf = %p\n", (void*) &hilf);
printf("Pointer von Inhalt auf den Zeiger hilf verweist = %p\n", (void*) hilf);
printf("Pointer von Char str Array, Member von struct hilf: hilf->str = %p\n", (void*) &(hilf->str));
free(hilf->str); // Zuerst den Speicher des Char Arrays auf das der Zeiger des Structs zeigt freigebenfree(hilf); // Und dann das Struct selbst.
return 0;
}
[cpp]==5604== Memcheck, a memory error detector ==5604== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al. ==5604== Using Valgrind-3.5.0-Debian and LibVEX; rerun with -h for copyright info ==5604== Command: ./freetest ==5604== Pointer von Zeiger hilf = 0x7ff000188 Pointer von Inhalt auf den Zeiger hilf verweist = 0x519a040 Pointer von Char str Array, Member von struct hilf: hilf->str = 0x519a048 ==5604== Invalid free() / delete / delete[] ==5604== at 0x4C24D68: free (vg_replace_malloc.c:325) ==5604== by 0x400647: main (in freetest) ==5604== Address 0x400750 is not stack'd, malloc'd or (recently) free'd ==5604== ==5604== ==5604== HEAP SUMMARY: ==5604== in use at exit: 15 bytes in 1 blocks ==5604== total heap usage: 2 allocs, 2 frees, 31 bytes allocated ==5604== ==5604== 15 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==5604== at 0x4C25153: malloc (vg_replace_malloc.c:195) ==5604== by 0x4005D8: main (in freetest) ==5604== ==5604== LEAK SUMMARY: ==5604== definitely lost: 15 bytes in 1 blocks ==5604== indirectly lost: 0 bytes in 0 blocks ==5604== possibly lost: 0 bytes in 0 blocks ==5604== still reachable: 0 bytes in 0 blocks ==5604== suppressed: 0 bytes in 0 blocks ==5604== ==5604== For counts of detected and suppressed errors, rerun with: -v ==5604== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 4 from 4)
definitely lost: 15 bytes in 1 blocks
-
Lies nochmal mein erstes Posting.
Du hast gesagt du hättest das korrigiert, ich seh aber nirgends ein strcpy, dafür verbiegst du immer noch hilf->str auf ein Stringliteral.
-
Bashar schrieb:
Lies nochmal mein erstes Posting.
Du hast gesagt du hättest das korrigiert, ich seh aber nirgends ein strcpy, dafür verbiegst du immer noch hilf->str auf ein Stringliteral.
Sorry, mein Fehler.
Ich habe hier noch ein zweites Programm, das eigentlich richtige und da habe ich strcpy korrigiert, aber von dem will ich nicht alles posten, daher nur das kurze Testprogramm und da habe ich es dummerweise vergessen. Sorry nochmal.
Jetzt funktioniert es, es lag an dem vergessenen strcpy.
Valgrind meldet keine Fehler mehr.Danke.
Hier nochmal der Code vom kompletten Testprogramm:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { struct element; typedef struct element *zeiger; struct element { int i; char *str; }; zeiger hilf; hilf = (zeiger) malloc(sizeof (struct element)); hilf->str = (char*) malloc(15 * sizeof (char)); strcpy(hilf->str, "Mein Text"); /* Nun geben wir den Speicher des Structs wieder frei: */ printf("Pointer von Zeiger hilf = %p\n", (void*) &hilf); printf("Pointer von Inhalt auf den Zeiger hilf verweist = %p\n", (void*) hilf); printf("Pointer von Char str Array, Member von struct hilf: hilf->str = %p\n", (void*) &(hilf->str)); free(hilf->str); // Zuerst den Speicher des Char Arrays auf das der Zeiger des Structs zeigt freigeben free(hilf); // Und dann das Struct selbst. return 0; }
Und valgrind:
==5736== Memcheck, a memory error detector ==5736== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al. ==5736== Using Valgrind-3.5.0-Debian and LibVEX; rerun with -h for copyright info ==5736== Command: ./freetest ==5736== Pointer von Zeiger hilf = 0x7ff000188 Pointer von Inhalt auf den Zeiger hilf verweist = 0x519a040 Pointer von Char str Array, Member von struct hilf: hilf->str = 0x519a048 ==5736== ==5736== HEAP SUMMARY: ==5736== in use at exit: 0 bytes in 0 blocks ==5736== total heap usage: 2 allocs, 2 frees, 31 bytes allocated ==5736== ==5736== All heap blocks were freed -- no leaks are possible ==5736== ==5736== For counts of detected and suppressed errors, rerun with: -v ==5736== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)
-
BTW:
Ich muß hier mal ein Lob aussprechen, Valgrind ist ein richtig geiles Programm.
Ohne Valgrind hätte ich einige Fehler ohne Nachdenken jedenfalls nicht gefunden
und wenn man bedenkt, daß man auch durchaus mal etwas übersehen oder bedenken kann, dann schleichen sich solche Speicherlecks natürlich sehr schnell ein.
Mit Valgrind findet man diese jedenfalls ziemlich gut.Geiles Programm.