已释放strdup分配内存仍出现内存泄漏,求排查原因
问题分析与修复
你的代码中导致strdup相关内存泄漏的核心问题及修复方案如下:
核心问题
1. main函数的无限循环导致链表内存永远无法释放
main里的while(1)是无限循环,除非程序被强制终止(如信号中断),否则循环后的free_linkedlist()永远不会执行。所有添加到链表的节点(包括strdup分配的cmd_name内存)都无法在程序正常结束时释放,必然会被检测为内存泄漏。
2. remove_background_process的逻辑存在冗余(非泄漏直接原因,但可优化)
当前删除节点的逻辑重复了内存释放代码,且虽能正确释放单个节点的内存,但如果程序未通过该函数清空所有节点,又因死循环无法执行free_linkedlist(),泄漏问题依然存在。
修复方案
方案一:让程序能正常退出并执行内存释放
在循环中添加退出条件,比如捕获退出信号或检测用户指令,确保free_linkedlist()能被执行:
#include <signal.h> static volatile sig_atomic_t exit_flag = 0; void handle_sigint(int sig) { exit_flag = 1; } int main() { signal(SIGINT, handle_sigint); // 捕获Ctrl+C信号触发退出 while (!exit_flag) { // 原有业务逻辑 // execute_pipeline(l); } // 正常退出时释放所有内存 free_linkedlist(); return 0; }
方案二:优化remove_background_process的内存释放逻辑
简化重复代码,确保节点内存释放逻辑统一:
void remove_background_process(int pid) { struct background_processes *current = head; struct background_processes *prev = NULL; while (current != NULL) { if (pid == current->pid) { struct background_processes *to_free = current; // 调整链表指针 if (prev == NULL) { head = current->next; } else { prev->next = current->next; } // 释放内存(先释放strdup分配的字符串,再释放节点) free(to_free->cmd_name); free(to_free); // 继续遍历剩余节点 current = (prev == NULL) ? head : prev->next; } else { prev = current; current = current->next; } } }
额外建议
- 检查
strdup返回值:strdup内部调用malloc可能分配失败返回NULL,需添加错误处理避免后续崩溃:
current->cmd_name = strdup(name); if (current->cmd_name == NULL) { free(current); // 释放已分配的节点 exit(EXIT_FAILURE); }
内容的提问来源于stack exchange,提问作者Jix
相关产品推荐
相关产品推荐

