请求协助排查C语言_setenv函数中的内存泄漏问题
排查_setenv函数的内存泄漏问题
核心内存泄漏及逻辑错误点
- 错误释放strdup内存:for循环的else分支中,把
strdup得到的current_env赋值给new_environ[i]后立即free(current_env),导致new_environ[i]成为野指针,同时新环境数组无法正确持有原有环境变量,后续还会引发非法内存访问问题。 - 未完整复制原有环境变量:找到匹配的环境变量时直接break循环,
new_environ中前i个元素(除当前循环项外)未被赋值,malloc的数组内这部分位置为垃圾值,原有环境变量也未复制到新数组,已strdup的内存未正确处理。 - 重复分配内存导致泄漏:找到匹配项时已分配
new_environ[count]并赋值,后续又进入if(!modified)分支再次分配,第一次分配的内存未被释放,直接泄漏。 - 内存分配失败未回滚:当
new_environ[count]分配失败时,未释放已分配的new_environ数组和已strdup的内存,导致泄漏。 - modified标志逻辑混乱:初始值与分支修改逻辑冲突,导致后续判断是否新增环境变量的逻辑出错。
修复后的代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> extern char **environ; int _setenv(const char *name, const char *value) { char **new_environ, *current_env, *env_name, *temp; int count = 0, i = 0; int found = 0; // 标记是否找到匹配的环境变量 // 统计环境变量数量 while (environ[i]) { count++; i++; } // 分配新的环境数组,+2用于新增变量和终止符 new_environ = malloc(sizeof(char *) * (count + 2)); if (!new_environ) { perror("Memory Allocation Error"); return (-1); } // 复制并检查原有环境变量 for (i = 0; i < count; i++) { current_env = strdup(environ[i]); if (!current_env) { // 分配失败,回滚已分配内存 for (int j = 0; j < i; j++) free(new_environ[j]); free(new_environ); perror("strdup failed"); return (-1); } temp = strdup(current_env); // 用临时副本拆分,避免破坏原strdup内容 if (!temp) { free(current_env); for (int j = 0; j < i; j++) free(new_environ[j]); free(new_environ); perror("strdup failed"); return (-1); } env_name = strtok(temp, "="); if (env_name != NULL && strcmp(env_name, name) == 0) { // 找到匹配项,替换为新值 free(current_env); free(temp); new_environ[i] = malloc(strlen(name) + strlen(value) + 2); if (!new_environ[i]) { for (int j = 0; j < i; j++) free(new_environ[j]); free(new_environ); perror("malloc failed"); return (-1); } sprintf(new_environ[i], "%s=%s", name, value); found = 1; } else { // 未找到匹配,保留原环境变量 new_environ[i] = current_env; free(temp); } } if (!found) { // 未找到匹配项,新增环境变量 new_environ[count] = malloc(strlen(name) + strlen(value) + 2); if (!new_environ[count]) { for (int j = 0; j < count; j++) free(new_environ[j]); free(new_environ); perror("malloc failed"); return (-1); } sprintf(new_environ[count], "%s=%s", name, value); new_environ[count + 1] = NULL; } else { // 已完成替换,终止数组 new_environ[count] = NULL; } // 替换全局environ(注:若之前的environ为自行分配,需额外free,此处默认是系统初始environ) environ = new_environ; return (0); }
修复说明
- 用
found替代modified,逻辑更清晰,明确标记是否找到匹配的环境变量。 - 拆分环境变量名时使用临时副本,避免破坏
strdup得到的原内容。 - 不再错误释放
new_environ[i]指向的strdup内存,让新环境数组正确持有这些内存。 - 内存分配失败时回滚所有已分配资源,彻底避免泄漏。
- 移除重复分配逻辑,仅在未找到匹配项时新增环境变量。
- 完整复制所有原有环境变量,避免
new_environ数组出现未初始化指针。
内容的提问来源于stack exchange,提问作者Imane
相关产品推荐
相关产品推荐

