Reputation: 131
I have this structure
struct room {
char* name;
char* description;
struct room *north;
struct room *south;
struct room *east;
struct room *west;
struct container* items;
};
So I should write a function
struct room* destroy_room(struct room* room);
that frees all the memory used for room creation and return NULL as new room reference.
So i thought that simply doing
free(room);
return NULL;
would resolve the problem, but it didn't.
Upvotes: 1
Views: 66
Reputation: 3498
I would go with a solution using two seperate functions. The first is destroy_room
it will free one single room and remove the references to itself from its neighbors:
struct room* destroy_room(struct room* room) {
if (!room) return;
if (room->name) free(room->name);
if (room->description) free(room->description);
if (room->items) free_items(room->items);
// remove the references to this room from its neighbors
if (room->north) room->north->south = NULL;
if (room->south) room->south->north = NULL;
if (room->east) room->east->west = NULL;
if (room->west) room->west->east = NULL;
free(room);
return NULL;
}
This function can then be used to write a recursive function ro free all rooms that are reachable from the given room. The function saves the references to the neighbors, then frees the given room and then recursivly frees the neighbors:
struct room* destroy_rooms_rec(struct room* room)
{
if (!room) return;
// save references to neighbors
struct room* north = room->north;
struct room* south = room->south;
struct room* east = room->east;
struct room* west = room->west;
// free this room
destroy_room(room);
// free all neighbors
destroy_rooms_rec(north);
destroy_rooms_rec(south);
destroy_rooms_rec(east);
destroy_rooms_rec(west);
return NULL;
}
Note: I assumed that a function like free_items(struct container* items)
exists that can free whatever items
is.
EDIT: I noticed that this code has a implicit assumtions. It assumes that the graph build by the rooms has a tree structure. If the graph is a fully conected grid or has any cycles this code won't work and leeds to memory problems like double free and invalid access.
But I'm working on a solution for any graph
Upvotes: 4
Reputation: 25276
As Jabberwocky says, "nothing is freed automatically", so your function could look like:
void destroy_room(struct room* room)
{
if (!room) return;
if (room->name) free(room->name);
if (room->description) free(room->description);
if (room!=room->north) destroy_room(room->north);
if (room!=room->south) destroy_room(room->south);
if (room!=room->east) destroy_room(room->east);
if (room!=room->west) destroy_room(room->west);
free_items(room->items);
free(room);
}
Upvotes: 2