与释放 C 中的内存混淆?
Confusion with freeing memory in C?
我对我在这里做错了什么感到非常困惑。我有一个节点链接列表(结构见下文),我对如何在修剪列表时释放内存感到困惑。我认为将它们添加到数组 (eventArr
) 会使它们以后更容易释放,但我仍然遇到问题!谁能帮我指出正确的方向?
static void trim_list(int room, int keep, char timestamp[]) {
struct room_t *the_room;
struct room_t *the_room_copy;
struct evnode_t *eventArr[20];
int index = 0;
the_room_copy = malloc(sizeof(struct room_t));
the_room = find_room(room);
the_room_copy->room = the_room->room;
the_room_copy->ecount = the_room->ecount;
the_room_copy->evl_head = the_room->evl_head;
struct evnode_t *node;
int counter;
int removed = 0;
for(counter = 0; counter != keep; counter++){
the_room_copy->evl_head = the_room_copy->evl_head->next;
}
while(the_room_copy->evl_head){
eventArr[index] = the_room_copy->evl_head;
the_room_copy->evl_head = the_room_copy->evl_head->next;
index++;
removed++;
}
for(index = 0; index < removed; index++){
free(eventArr[index]);
}
printf("Trim log @ %s: room %i log trimmed to length %i (%i entries removed)\n",timestamp, room, keep, removed);
return ;
}
结构:
struct evnode_t {
struct event_t event ;
struct evnode_t *next ;
} ;
struct room_t {
int room ;
int ecount ;
struct evnode_t *evl_head ;
struct room_t *next_room ;
} ;
struct event_t {
int sensor ;
char time_stamp[MAX_TIMESTRING+1];
int event_id ;
int event_info ;
} ;
我应该注意,我 运行 通过 gdb 进行此操作是为了更好地理解它,但由于某种原因,这些值变得一团糟。这是我的输出:
之前 运行 trim_list...
(gdb) p room_list->room
= 1
(gdb) p room_list->evl_head->event.sensor
= 9
(gdb) p room_list->evl_head->next->event.sensor
= 4
(gdb) p room_list->evl_head->next->next->event.sensor
= 2
(gdb) p room_list->evl_head->next->next->next->event.sensor
= 2
(gdb) p room_list->evl_head->next->next->next->next->event.sensor
= 3
(gdb) p room_list->evl_head->next->next->next->next->next->event.sensor
= 2
在运行之后trim_list...
(gdb) p room_list->evl_head->next->event.sensor
= 4
(gdb) p room_list->evl_head->next->next->event.sensor
= 2
(gdb) p room_list->evl_head->next->next->next->event.sensor
= 2
(gdb) p room_list->evl_head->next->next->next->next->event.sensor
= 0
(gdb) p room_list->evl_head->next->next->next->next->next->event.sensor
= 6396880
任何关于我为什么会遇到这些问题的见解都将非常有帮助!我不确定我是否正确理解了如何释放值...但是我知道被释放的值都已 malloc
ed。澄清一下,room_list
是我试图从中释放值的列表,the_room_copy
是 room_list
.
的新 malloc
ed 版本
看起来您正在正确释放节点。您没有做的是在新位置终止列表。例如,如果旧列表是:
1 -> 9 -> 4 -> 2 -> 2 -> 3 -> 2 -> NULL
而你想在第 5 个元素之后 trim,你现在所做的结果是这样的:
1 -> 9 -> 4 -> 2 -> 2 -> (freed memory) -> (unknown pointer) -> ...
你需要做的是在你想保留的链表之后终止链表:
1 -> 9 -> 4 -> 2 -> 2 -> NULL
下面是一些示例代码,显示了一种终止列表的方法:
struct evnode_t *end_of_list = NULL;
// This is your existing loop to skip past "keep" elements.
for(counter = 0; counter != keep; counter++){
end_of_list = the_room_copy->evl_head;
the_room_copy->evl_head = the_room_copy->evl_head->next;
}
// Free stuff as you did before...
// At the very end:
if (end_of_list == NULL) {
// Keep nothing.
the_room->evl_head = NULL;
} else {
// Terminate the list at the proper place.
end_of_list->next = NULL;
}
// Oh, you need to free the copy also, it's a memory leak:
free(the_room_copy);
添加到 JS1 先生的答案中,要终止链表,您需要添加类似这样的代码:
struct evnode_t *node_to_terminate = the_room->evl_head;
for (int i = 1; i < keep; ++i)
{
node_to_terminate = node_to_terminate->evl_head;
}
node_terminate->next = NULL;
我对我在这里做错了什么感到非常困惑。我有一个节点链接列表(结构见下文),我对如何在修剪列表时释放内存感到困惑。我认为将它们添加到数组 (eventArr
) 会使它们以后更容易释放,但我仍然遇到问题!谁能帮我指出正确的方向?
static void trim_list(int room, int keep, char timestamp[]) {
struct room_t *the_room;
struct room_t *the_room_copy;
struct evnode_t *eventArr[20];
int index = 0;
the_room_copy = malloc(sizeof(struct room_t));
the_room = find_room(room);
the_room_copy->room = the_room->room;
the_room_copy->ecount = the_room->ecount;
the_room_copy->evl_head = the_room->evl_head;
struct evnode_t *node;
int counter;
int removed = 0;
for(counter = 0; counter != keep; counter++){
the_room_copy->evl_head = the_room_copy->evl_head->next;
}
while(the_room_copy->evl_head){
eventArr[index] = the_room_copy->evl_head;
the_room_copy->evl_head = the_room_copy->evl_head->next;
index++;
removed++;
}
for(index = 0; index < removed; index++){
free(eventArr[index]);
}
printf("Trim log @ %s: room %i log trimmed to length %i (%i entries removed)\n",timestamp, room, keep, removed);
return ;
}
结构:
struct evnode_t {
struct event_t event ;
struct evnode_t *next ;
} ;
struct room_t {
int room ;
int ecount ;
struct evnode_t *evl_head ;
struct room_t *next_room ;
} ;
struct event_t {
int sensor ;
char time_stamp[MAX_TIMESTRING+1];
int event_id ;
int event_info ;
} ;
我应该注意,我 运行 通过 gdb 进行此操作是为了更好地理解它,但由于某种原因,这些值变得一团糟。这是我的输出:
之前 运行 trim_list...
(gdb) p room_list->room
= 1
(gdb) p room_list->evl_head->event.sensor
= 9
(gdb) p room_list->evl_head->next->event.sensor
= 4
(gdb) p room_list->evl_head->next->next->event.sensor
= 2
(gdb) p room_list->evl_head->next->next->next->event.sensor
= 2
(gdb) p room_list->evl_head->next->next->next->next->event.sensor
= 3
(gdb) p room_list->evl_head->next->next->next->next->next->event.sensor
= 2
在运行之后trim_list...
(gdb) p room_list->evl_head->next->event.sensor
= 4
(gdb) p room_list->evl_head->next->next->event.sensor
= 2
(gdb) p room_list->evl_head->next->next->next->event.sensor
= 2
(gdb) p room_list->evl_head->next->next->next->next->event.sensor
= 0
(gdb) p room_list->evl_head->next->next->next->next->next->event.sensor
= 6396880
任何关于我为什么会遇到这些问题的见解都将非常有帮助!我不确定我是否正确理解了如何释放值...但是我知道被释放的值都已 malloc
ed。澄清一下,room_list
是我试图从中释放值的列表,the_room_copy
是 room_list
.
malloc
ed 版本
看起来您正在正确释放节点。您没有做的是在新位置终止列表。例如,如果旧列表是:
1 -> 9 -> 4 -> 2 -> 2 -> 3 -> 2 -> NULL
而你想在第 5 个元素之后 trim,你现在所做的结果是这样的:
1 -> 9 -> 4 -> 2 -> 2 -> (freed memory) -> (unknown pointer) -> ...
你需要做的是在你想保留的链表之后终止链表:
1 -> 9 -> 4 -> 2 -> 2 -> NULL
下面是一些示例代码,显示了一种终止列表的方法:
struct evnode_t *end_of_list = NULL;
// This is your existing loop to skip past "keep" elements.
for(counter = 0; counter != keep; counter++){
end_of_list = the_room_copy->evl_head;
the_room_copy->evl_head = the_room_copy->evl_head->next;
}
// Free stuff as you did before...
// At the very end:
if (end_of_list == NULL) {
// Keep nothing.
the_room->evl_head = NULL;
} else {
// Terminate the list at the proper place.
end_of_list->next = NULL;
}
// Oh, you need to free the copy also, it's a memory leak:
free(the_room_copy);
添加到 JS1 先生的答案中,要终止链表,您需要添加类似这样的代码:
struct evnode_t *node_to_terminate = the_room->evl_head;
for (int i = 1; i < keep; ++i)
{
node_to_terminate = node_to_terminate->evl_head;
}
node_terminate->next = NULL;