内存泄漏读取文件到 C 中的链表
Memory Leak Reading File to Linked List in C
学习如何使用链表,我在将文件读入一个文件时遇到内存泄漏问题。
我的代码如下所示:
const struct dhcp_ops dhcp_exec;
struct dhcp_list {
char mac[18];
char ip[20];
char name[255];
struct dhcp_list *next;
}*conductor;
struct dhcp_ops {
void (*clients)(struct dhcp_list **);
};
void get_clients(struct dhcp_list **buf)
{
FILE *fp;
char line[128];
struct dhcp_list *ptr;
ptr = (struct dhcp_list*)malloc(sizeof(struct dhcp_list));
ptr->next = NULL;
conductor = ptr;
fp = fopen(DHCP_LEASES, "r");
if(NULL == fp)
return;
char created[10];
char mask[5];
while(fgets(line, sizeof(line), fp) != NULL){
ptr->next = malloc(sizeof(struct dhcp_list));
if (ptr->next == NULL) break;
sscanf(line, "%s %s %s %s %s\n",
created,
ptr->mac,
ptr->ip,
ptr->name,
mask);
ptr = ptr->next;
ptr->next = NULL;
}
fclose(fp);
*buf = conductor;
}
并将调用/格式化的块变成JSON,以供演示。
void format_dhcp(json_object *jdhcp_array)
{
const struct dhcp_ops *dhcp;
struct dhcp_list *clients = (struct dhcp_list*)malloc(sizeof(struct dhcp_list));
dhcp = &dhcp_exec;
dhcp->clients(&clients);
while (clients->next != NULL) {
printf("MAC ADDRESS: %s\n", clients->mac);
json_object *jdhcp = json_object_new_object();
json_object *jmac = json_object_new_string(tmp->mac);
json_object_object_add(jdhcp, "mac", jmac);
clients = clients->next;
}
struct dhcp_list *freeMe = clients;
struct dhcp_list *holdMe = NULL;
while(freeMe->next != NULL) {
holdMe = freeMe->next;
free(freeMe);
freeMe = holdMe;
}
// free(clients);
}
const struct dhcp_ops dhcp_exec = {
.clients = get_clients,
};
当我 运行 使用 valgrind 时,出现以下错误:
==2925== HEAP SUMMARY:
==2925== in use at exit: 2,128 bytes in 7 blocks
==2925== total heap usage: 1,756 allocs, 1,749 frees, 357,725 bytes allocated
==2925==
==2925== 304 bytes in 1 blocks are definitely lost in loss record 2 of 3
==2925== at 0x4C27C0F: malloc (vg_replace_malloc.c:299)
==2925== by 0x405176: format_dhcp (collector.c:479)
==2925== by 0x4056DF: collect_data (collector.c:637)
==2925== by 0x4057DB: collect_and_send_data (collector.c:669)
==2925== by 0x405E35: monitor (monitor.c:165)
==2925== by 0x40AA05: run_collector (boot.c:115)
==2925== by 0x40AB10: boot (boot.c:152)
==2925== by 0x409DE1: main (socketman.c:242)
==2925==
==2925== LEAK SUMMARY:
==2925== definitely lost: 304 bytes in 1 blocks
==2925== indirectly lost: 0 bytes in 0 blocks
==2925== possibly lost: 0 bytes in 0 blocks
==2925== still reachable: 1,824 bytes in 6 blocks
==2925== suppressed: 0 bytes in 0 blocks
==2925== Reachable blocks (those to which a pointer was found) are not shown.
==2925== To see them, rerun with: --leak-check=full --show-leak-kinds=all
我通过将 'free block' 移动到读取文件的主函数中进行了测试。这 运行 非常完美,没有泄漏。显然,我没有得到输出。
有人可以建议我哪里出错了/我需要做什么才能正确清除内存。
------------ 编辑已解决 ----------------------
根据评论和答案,我实施了更改。之后,我摆脱了丢失的字节。但是,我仍然可以访问 1800+。
==10669== LEAK SUMMARY:
==10669== definitely lost: 0 bytes in 0 blocks
==10669== indirectly lost: 0 bytes in 0 blocks
==10669== possibly lost: 0 bytes in 0 blocks
==10669== still reachable: 1,824 bytes in 6 blocks
==10669== suppressed: 0 bytes in 0 blocks
==10669== Reachable blocks (those to which a pointer was found) are not shown.
==10669== To see them, rerun with: --leak-check=full --show-leak-kinds=all
事实证明,客户端总是在第一个循环之后。因此,我将 freeMe 结构移动到第一个循环上方以解决问题:
void format_dhcp(json_object *jdhcp_array)
{
const struct dhcp_ops *dhcp;
struct dhcp_list *clients = NULL;
dhcp = &dhcp_exec;
dhcp->clients(&clients);
struct dhcp_list *freeMe = clients;
while (clients->next != NULL) {
printf("MAC ADDRESS: %s\n", clients->mac);
json_object *jdhcp = json_object_new_object();
json_object *jmac = json_object_new_string(clients->mac);
json_object_object_add(jdhcp, "mac", jmac);
json_object *jip = json_object_new_string(clients->ip);
json_object_object_add(jdhcp, "ip", jip);
json_object *jname = json_object_new_string(clients->name);
json_object_object_add(jdhcp, "name", jname);
json_object_array_add(jdhcp_array, jdhcp);
clients = clients->next;
}
struct dhcp_list *holdMe = NULL;
while(freeMe != NULL) {
debug("Should be freed");
holdMe = freeMe->next;
free(freeMe);
freeMe = holdMe;
}
}
条件freeMe->next != NULL
,最后一个元素不会被释放。
18 + 20 + 255 = 293
,所以"lost" 304字节应该是一个struct dhcp_list
。 (左边11个字节应该是一个指针+padding)
请尝试使用 freeMe != NULL
。
另请注意,他们说 you shouldn't cast the result of malloc()
in C。
这是另一个内存泄漏:
您在行中分配了一些内存
struct dhcp_list *clients = (struct dhcp_list*)malloc(sizeof(struct dhcp_list));
但是你在 dhcp->clients
中根本没有使用它就把地址扔掉了,也就是 get_clients
。
停止分配如此浪费的内存,只需像
这样的变量声明即可
struct dhcp_list *clients;
或者为了更安全,以防万一 dhcp->clients
没有正常工作,将它初始化为 NULL
并在调用函数后检查它的值是否仍然是 NULL
。
问题出在format_dhcp
:
struct dhcp_list *clients = (struct dhcp_list*)malloc(sizeof(struct dhcp_list));
^^^^^^^ here you allocate memory for clients
dhcp = &dhcp_exec;
dhcp->clients(&clients);
^^^^^^ here you call get_clients
在get_clients
你做:
ptr = (struct dhcp_list*)malloc(sizeof(struct dhcp_list));
ptr->next = NULL;
conductor = ptr;
....
*buf = conductor;
^^^^^
Now the original clients is lost and you have a leak
您从未在 format_dhcp
中使用分配给 clients
的内存,并且覆盖了 get_clients
中的指针,这导致了泄漏。
所以结论是:不要在 format_dhcp
中执行 malloc
- 你不需要它。
学习如何使用链表,我在将文件读入一个文件时遇到内存泄漏问题。
我的代码如下所示:
const struct dhcp_ops dhcp_exec;
struct dhcp_list {
char mac[18];
char ip[20];
char name[255];
struct dhcp_list *next;
}*conductor;
struct dhcp_ops {
void (*clients)(struct dhcp_list **);
};
void get_clients(struct dhcp_list **buf)
{
FILE *fp;
char line[128];
struct dhcp_list *ptr;
ptr = (struct dhcp_list*)malloc(sizeof(struct dhcp_list));
ptr->next = NULL;
conductor = ptr;
fp = fopen(DHCP_LEASES, "r");
if(NULL == fp)
return;
char created[10];
char mask[5];
while(fgets(line, sizeof(line), fp) != NULL){
ptr->next = malloc(sizeof(struct dhcp_list));
if (ptr->next == NULL) break;
sscanf(line, "%s %s %s %s %s\n",
created,
ptr->mac,
ptr->ip,
ptr->name,
mask);
ptr = ptr->next;
ptr->next = NULL;
}
fclose(fp);
*buf = conductor;
}
并将调用/格式化的块变成JSON,以供演示。
void format_dhcp(json_object *jdhcp_array)
{
const struct dhcp_ops *dhcp;
struct dhcp_list *clients = (struct dhcp_list*)malloc(sizeof(struct dhcp_list));
dhcp = &dhcp_exec;
dhcp->clients(&clients);
while (clients->next != NULL) {
printf("MAC ADDRESS: %s\n", clients->mac);
json_object *jdhcp = json_object_new_object();
json_object *jmac = json_object_new_string(tmp->mac);
json_object_object_add(jdhcp, "mac", jmac);
clients = clients->next;
}
struct dhcp_list *freeMe = clients;
struct dhcp_list *holdMe = NULL;
while(freeMe->next != NULL) {
holdMe = freeMe->next;
free(freeMe);
freeMe = holdMe;
}
// free(clients);
}
const struct dhcp_ops dhcp_exec = {
.clients = get_clients,
};
当我 运行 使用 valgrind 时,出现以下错误:
==2925== HEAP SUMMARY:
==2925== in use at exit: 2,128 bytes in 7 blocks
==2925== total heap usage: 1,756 allocs, 1,749 frees, 357,725 bytes allocated
==2925==
==2925== 304 bytes in 1 blocks are definitely lost in loss record 2 of 3
==2925== at 0x4C27C0F: malloc (vg_replace_malloc.c:299)
==2925== by 0x405176: format_dhcp (collector.c:479)
==2925== by 0x4056DF: collect_data (collector.c:637)
==2925== by 0x4057DB: collect_and_send_data (collector.c:669)
==2925== by 0x405E35: monitor (monitor.c:165)
==2925== by 0x40AA05: run_collector (boot.c:115)
==2925== by 0x40AB10: boot (boot.c:152)
==2925== by 0x409DE1: main (socketman.c:242)
==2925==
==2925== LEAK SUMMARY:
==2925== definitely lost: 304 bytes in 1 blocks
==2925== indirectly lost: 0 bytes in 0 blocks
==2925== possibly lost: 0 bytes in 0 blocks
==2925== still reachable: 1,824 bytes in 6 blocks
==2925== suppressed: 0 bytes in 0 blocks
==2925== Reachable blocks (those to which a pointer was found) are not shown.
==2925== To see them, rerun with: --leak-check=full --show-leak-kinds=all
我通过将 'free block' 移动到读取文件的主函数中进行了测试。这 运行 非常完美,没有泄漏。显然,我没有得到输出。
有人可以建议我哪里出错了/我需要做什么才能正确清除内存。
------------ 编辑已解决 ----------------------
根据评论和答案,我实施了更改。之后,我摆脱了丢失的字节。但是,我仍然可以访问 1800+。
==10669== LEAK SUMMARY:
==10669== definitely lost: 0 bytes in 0 blocks
==10669== indirectly lost: 0 bytes in 0 blocks
==10669== possibly lost: 0 bytes in 0 blocks
==10669== still reachable: 1,824 bytes in 6 blocks
==10669== suppressed: 0 bytes in 0 blocks
==10669== Reachable blocks (those to which a pointer was found) are not shown.
==10669== To see them, rerun with: --leak-check=full --show-leak-kinds=all
事实证明,客户端总是在第一个循环之后。因此,我将 freeMe 结构移动到第一个循环上方以解决问题:
void format_dhcp(json_object *jdhcp_array)
{
const struct dhcp_ops *dhcp;
struct dhcp_list *clients = NULL;
dhcp = &dhcp_exec;
dhcp->clients(&clients);
struct dhcp_list *freeMe = clients;
while (clients->next != NULL) {
printf("MAC ADDRESS: %s\n", clients->mac);
json_object *jdhcp = json_object_new_object();
json_object *jmac = json_object_new_string(clients->mac);
json_object_object_add(jdhcp, "mac", jmac);
json_object *jip = json_object_new_string(clients->ip);
json_object_object_add(jdhcp, "ip", jip);
json_object *jname = json_object_new_string(clients->name);
json_object_object_add(jdhcp, "name", jname);
json_object_array_add(jdhcp_array, jdhcp);
clients = clients->next;
}
struct dhcp_list *holdMe = NULL;
while(freeMe != NULL) {
debug("Should be freed");
holdMe = freeMe->next;
free(freeMe);
freeMe = holdMe;
}
}
条件freeMe->next != NULL
,最后一个元素不会被释放。
18 + 20 + 255 = 293
,所以"lost" 304字节应该是一个struct dhcp_list
。 (左边11个字节应该是一个指针+padding)
请尝试使用 freeMe != NULL
。
另请注意,他们说 you shouldn't cast the result of malloc()
in C。
这是另一个内存泄漏:
您在行中分配了一些内存
struct dhcp_list *clients = (struct dhcp_list*)malloc(sizeof(struct dhcp_list));
但是你在 dhcp->clients
中根本没有使用它就把地址扔掉了,也就是 get_clients
。
停止分配如此浪费的内存,只需像
struct dhcp_list *clients;
或者为了更安全,以防万一 dhcp->clients
没有正常工作,将它初始化为 NULL
并在调用函数后检查它的值是否仍然是 NULL
。
问题出在format_dhcp
:
struct dhcp_list *clients = (struct dhcp_list*)malloc(sizeof(struct dhcp_list));
^^^^^^^ here you allocate memory for clients
dhcp = &dhcp_exec;
dhcp->clients(&clients);
^^^^^^ here you call get_clients
在get_clients
你做:
ptr = (struct dhcp_list*)malloc(sizeof(struct dhcp_list));
ptr->next = NULL;
conductor = ptr;
....
*buf = conductor;
^^^^^
Now the original clients is lost and you have a leak
您从未在 format_dhcp
中使用分配给 clients
的内存,并且覆盖了 get_clients
中的指针,这导致了泄漏。
所以结论是:不要在 format_dhcp
中执行 malloc
- 你不需要它。