Speichermanagement in C
-
Hallöle,
ich komme tendenziell eher von OOP Sprachen (bissl Java/ObjC/C++, nix richtig) und bin etwas erstaunt über Speichermanagement in C.
Wenn ich danach google finde ich nur Erklärungen zu malloc/realloc/free etc. Ist das alles? Was ist z.B. mit Reference Counting (release/retain) etc.?
Aus OOP kenne ich z.B. auch die Problematik, dass ein Objekt dafür verantwortlich ist, den Speicher, den es alloziert, auch wieder freizugeben; also wenn Obj A irgendwo ein new stehen hat, muss es auch wieder ein delete schreiben. Übertragen auf C hätte ich jetzt vermutet, dass dies für Funktionen gilt: Nutzt eine Funktion malloc, muss sie auch free nutzen. Scheint aber gar nicht zu gehen (sonst kann eine Funktion nichts zurückgeben, was durch malloc alloziert wurde) und das scheint auch keinen C-Programmierer zu stören... *verwirrt*
Was gibt es denn jetzt für Regeln für Speichermanagement in C?
Gruß, Micha
-
Grundlagen:
1. Du musst alles selber programmieren
2. Du brauchst viel DisziplinUmsetzung:
- Du bist schon auf gutem Weg, mit der Idee der objektorientierten Umsetzung.
- Wer ein Objekt anlegt ("Konstruktoraufruf"), der gibt es auch wieder frei ("Destruktor")
- Hieraus folgt, dass eine Funktion niemals rohen Speicher malloc'en und zurückgeben sollte. Sie verändert stattdessen ein Objekt, für das der Funktionsaufrufer die Verantwortung hat.Grundmuster (ungetestet)
typedef struct { // Hier drin ist alles als private im C++-Sinne anzusehen char * data; unsigned size; } foo; void construct_foo(foo *this, unsigned size) { this->data = malloc(size); this->size = size; } void destruct_foo(foo *this) { free(this->data); } // Kopierfunktion und Zuweisungsfunktion wären auch noch nützlich int main() { foo bar; // Für dieses foo-Objekt trägt main die Verantwortung construct_foo(&bar); // ... // Mach irgendwas mit dem Objekt // ... destroy_foo(&bar); }
-
Man muss Speicher mit malloc erzeugen und manuell mit free freigeben.
Es gibt keinerlei automatische Hilfsmittel.
Es gibt schon Funktionen die Speicher mit malloc erzeugen und den zurückgeben, nur muss der Speicher explizit an anderer Stelle freigegeben werden.int* create_arr(int size) {return malloc(sizeof(int)*size);} ... int main() { int *arr = create_arr(4); ... free(arr); return 0; }
Wenn du von OOP-Sprachen kommst, kannst du aber auch gewissermaßen OOP in C programmieren:
CLASS class = create_class(param1, param2); do_sth_with_class(class, param1, param2); do_sth_different_with_class(class, param1); destroy_class(class);
Den Speicher musst du aber trotzdem später freigeben.
Edit: Verdammt, zu langsam.
-
Reines C kennt keine OOP, also keine Objekte. Mit deinem Hintergrund nimmst du besser C++ oder C#. Auch VisualBasic kann in Frage kommen. Viel Glück mit dem Umstieg/Einstieg!
-
@Nathan: Dein erstes Beispiel ist, wie man es genau nicht machen sollte. So werden Implementierungsdetails der Funktion create_arr nach außen getragen. Wenn sich die Implementierung jemals ändert, muss aller Anwendungscode geändert werden. Wenn der Anwender die Doku nicht aufmerksam liest, geht es auch schief.
-
Ja, ist mir nachher auch klar geworden.
Selbst mit einer Wrapper-free-Funktion kann der DAU es immer noch falsch machen und auto-arrays löschen.
"Kapselung" ist da schon besser.
-
SeppJ schrieb:
Grundlagen:
1. Du musst alles selber programmieren
2. Du brauchst viel DisziplinSowas hab ich befürchtet *g*
SeppJ schrieb:
Umsetzung:
- Du bist schon auf gutem Weg, mit der Idee der objektorientierten Umsetzung.
- Wer ein Objekt anlegt ("Konstruktoraufruf"), der gibt es auch wieder frei ("Destruktor")
- Hieraus folgt, dass eine Funktion niemals rohen Speicher malloc'en und zurückgeben sollte. Sie verändert stattdessen ein Objekt, für das der Funktionsaufrufer die Verantwortung hat.Klingt tatsächlich sehr nach objektorientierter Programmierung. Umso besser, dann hab ich mehr Material zum lernen
-
SeppJ schrieb:
- Hieraus folgt, dass eine Funktion niemals rohen Speicher malloc'en und zurückgeben sollte. Sie verändert stattdessen ein Objekt, für das der Funktionsaufrufer die Verantwortung hat.
wie willst du das machen, wenn die anzahl der benötigen objekte erst zur laufzeit feststeht?
alle objekte in einem foo -struct-container kapseln?
-
jojoe schrieb:
SeppJ schrieb:
- Hieraus folgt, dass eine Funktion niemals rohen Speicher malloc'en und zurückgeben sollte. Sie verändert stattdessen ein Objekt, für das der Funktionsaufrufer die Verantwortung hat.
wie willst du das machen, wenn die anzahl der benötigen objekte erst zur laufzeit feststeht?
Wo ist das Problem? Entweder selber malloc machen (und sich selber um das Aufräumen kümmern) oder eine Container"klasse" benutzen.