Meillo hat geschrieben:
Verwaltest du die einzelnen Unterarrays dynamisch? Weil sonst wuerde ich die komplette Speicherflaeche mit einem einzigen malloc(3) anlegen: malloc(sizeof(char *) * n * m)
Ich poste mal den tatsächlichen Code (es geht um das "Monty Hall"-Problem, siehe Smalltalk-Forum):
Code: Alles auswählen
char **init_games(int n_games, int doors)
{
int game;
char **games;
games = (char**)malloc(sizeof(char*) * n_games);
if (games == NULL) {
fail("cannot allocate memory for games");
}
for (game = 0; game < n_games; game++) {
games[game] = (char*)malloc(sizeof(char) * doors);
if (games[game] == NULL) {
fail("cannot allocate memory for doors");
}
}
return games;
}
Und hier der Aufruf dazu:
Code: Alles auswählen
char **games = NULL;
// [,..]
games = init_games(n_games, 3);
Wenn ich das mit einem
malloc versuche, bekomme ich später einen Segmentation-Fault:
Code: Alles auswählen
games = (char**)malloc(sizeof(char *) * n_games * doors);
Müsste ich nicht statt
char * einfach
char nehmen? (Geht leider auch nicht.) Irgendwie stehe ich da auf dem Schlauch.
Meillo hat geschrieben:
Wenn du nur am Programmende den Speicher freigibst (weil der Speicher nur genau einmal angelegt wird und dann die ganze Programmlaufzeit konstant bleibt), dann kannst du dir das auch ganz sparen, weil am Programmende sowieso aller Speicher freigegeben wird. Dies wird von verschiedenen Personen wohl unterschiedlich gesehen werden, ich unterscheide in meiner Sichtweise halt zwischen Speicherflaechen, die nur einmal alloziert werden und dann die ganze Laufzeit lang konstant vorhanden sind und welchen, die im Betrieb angelegt und freigegeben werden.
Sagen wir es mal so: Bei meinem aktuellen Programm ist es eigentlich nicht nötig. Wenn aber die Simulation immer und immer wieder mit anderen Werten laufen sollte, die der Benutzer interaktiv eingibt, wäre es schon nötig.
Dazu noch eine weitere Frage: Ginge das
free dann auch in einem Schritt? Im Moment mache ich:
Code: Alles auswählen
for (game = 0; game < n_games; game++) {
free(games[game]);
}
free(games);
Meillo hat geschrieben:
Ich habe von der Faustregel gehört, dass eine Funktion, die Speicher reserviert, denselben Speicher auch immer wieder freigeben sollte.
Das kann natuerlich so nicht sein, weil wenn die Funktion den Speicher gleich wieder freigibt, dann hat man ja nichts davon.
Natürlich, aber dann wäre es ja ein Argument, das
malloc nicht in eine Unterfunktion auszulagern, weil das Programm so gar nicht umzusetzen wäre.
Meillo hat geschrieben:
Die Regel ist, dass Allozierung und Freigabe auf dem gleichen Layer passieren sollen. Wenn du also eine Funktion anbietest, die Speicher alloziert, dann sollest du auch eine anbieten, die diesen Speicher wieder freigibt ... z.B. createobj() und deleteobj(). Man sagt, dass man bei der Speicherverwaltung immer eine Symmetrie von Allozierung und Freigeben haben will.
Das dürfte die Regel sein, die ich damals aufgeschnappt, aber nicht richtig verstanden habe:
malloc und
free müssen nicht in der gleichen Funktion stehen, sie sollten einfach im Call-Stack auf der gleichen Ebene stehen, wenn man das so ausdrücken kann...?
Meillo hat geschrieben:
[...] die init()-Funktion nur für die Initialisierung der eigentlichen Werte verwendet werden?
Ich denke, es muss halt klar und einheitlich sein. Der Begriff ``init'' wird manchmal als ``create'' verstanden und manchmal nur als ``set initial state'', darum ist nicht unbedingt klar, ob eine Funktion diesen Namens das ``Objekt'' erzeugt oder nur ein gegebenes Objekt in den Initialzustand versetzt.
Mit dem oben behandelten wäre ja das Reservieren des Speichers legitim. Ich habe gerade erst gemerkt, dass ich die eigentliche Initialisierung doch in
main drin hatte, von daher sollte die Funktion eher
alloc statt
init heissen.