You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请求协助排查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);
}

修复说明

  1. 用found替代modified,逻辑更清晰,明确标记是否找到匹配的环境变量。
  2. 拆分环境变量名时使用临时副本,避免破坏strdup得到的原内容。
  3. 不再错误释放new_environ[i]指向的strdup内存,让新环境数组正确持有这些内存。
  4. 内存分配失败时回滚所有已分配资源,彻底避免泄漏。
  5. 移除重复分配逻辑,仅在未找到匹配项时新增环境变量。
  6. 完整复制所有原有环境变量,避免new_environ数组出现未初始化指针。

内容的提问来源于stack exchange,提问作者Imane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 13:01:16