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

C语言get_next_line函数内存泄漏问题求助

内存泄漏问题分析与修复

你的代码存在多处内存泄漏,核心是动态分配的内存未被及时释放,尤其是ft_strdup、ft_strjoin分配的内存,以及静态变量leftover的管理逻辑缺陷,具体问题和修复方案如下:

核心泄漏点

  • ft_strjoin返回的ft_strdup内存丢失:第一次调用ft_read_from_file时,leftover为NULL,ft_strjoin会返回ft_strdup(buffer)的指针,后续get_next_line用ft_strchr的返回值覆盖leftover,原内存块彻底无法释放。
  • ft_read_from_file中旧leftover未释放:当leftover已有内容时,ft_strjoin分配新内存,但旧指针被直接覆盖,没有执行free操作。
  • get_next_line中leftover的覆盖逻辑错误:leftover = ft_strchr(leftover, '\n');直接用原字符串内的指针覆盖了malloc分配的指针,导致整个旧内存块丢失。
  • 静态leftover终态泄漏:程序运行期间,leftover若有剩余内容,未在合适时机释放。

修复后的完整代码

#include <stdlib.h>
#include <unistd.h>

// 辅助函数声明
char    *ft_strchr(const char *s, int c);
char    *ft_strjoin(char const *s1, char const *s2);
char    *ft_strdup(const char *s1);
int ft_strlen(const char *str);
char    *ft_find_line(char *leftover);
char    *ft_read_from_file(int fd, char *leftover);

char    *get_next_line(int fd)
{
    static char *leftover;
    char        *next_line;
    char        *temp_leftover; // 保存旧leftover指针用于释放

    if (BUFFER_SIZE <= 0 || fd < 0)
        return (NULL);
    if (!leftover)
        leftover = ft_read_from_file(fd, leftover);
    if (!leftover)
        return (NULL);
    next_line = ft_find_line(leftover);
    temp_leftover = leftover;
    leftover = ft_strchr(leftover, '\n');
    if (leftover)
    {
        leftover++;
        leftover = ft_strdup(leftover); // 复制剩余内容到新内存
    }
    else
    {
        leftover = NULL; // 无剩余内容时置空
    }
    free(temp_leftover); // 释放原leftover内存块
    return (next_line);
}

char    *ft_read_from_file(int fd, char *leftover)
{
    char        *buffer;
    long long   bytes_read;
    char        *temp_str; // 保存旧leftover指针

    buffer = malloc(sizeof(char) * (BUFFER_SIZE + 1));
    if (!buffer)
        return (NULL);
    bytes_read = read(fd, buffer, BUFFER_SIZE);
    if (bytes_read < 0) // 区分读取错误与EOF
    {
        free(buffer);
        return (NULL);
    }
    else if (bytes_read == 0)
    {
        free(buffer);
        return leftover; // EOF时返回原leftover
    }
    buffer[bytes_read] = '\0';
    temp_str = leftover;
    leftover = ft_strjoin(leftover, buffer);
    free(buffer);
    free(temp_str); // 释放旧leftover内存
    return (leftover);
}

char    *ft_find_line(char *leftover)
{
    char    *str;
    int     i;
    int     j;

    j = 0;
    i = 0;
    while (leftover[i] != '\n' && leftover[i])
        i++;
    str = malloc(sizeof(char) * (i + 2));
    if (!str) // 增加malloc失败判断
        return NULL;
    while (j <= i) // 修正循环条件,确保复制到换行符或末尾
    {
        str[j] = leftover[j];
        j++;
    }
    str[j] = '\0';
    return (str);
}

char    *ft_strchr(const char *s, int c)
{
    int i;

    i = 0;
    while (s[i] && s[i] != (char)c) // 移除BUFFER_SIZE限制,避免截断长行
        i++;
    if (s[i] == (char)c)
        return ((char *)&s[i]);
    return (NULL);
}

char    *ft_strjoin(char const *s1, char const *s2)
{
    int     i;
    int     j;
    char    *str;

    i = 0;
    j = 0;
    if (!s1 && !s2)
        return (NULL);
    if (!s1)
        return (ft_strdup(s2));
    if (!s2)
        return (ft_strdup(s1)); // 处理s2为NULL的情况
    str = malloc((ft_strlen(s1) + ft_strlen(s2) + 1) * sizeof(char));
    if (str == NULL)
        return (NULL);
    while (s1[i])
    {
        str[j++] = s1[i++];
    }
    i = 0;
    while (s2[i])
    {
        str[j++] = s2[i++];
    }
    str[j] = '\0';
    return (str);
}

char    *ft_strdup(const char *s1)
{
    int     i;
    int     size;
    char    *ptr;

    i = 0;
    size = ft_strlen(s1);
    ptr = malloc(sizeof(char) * (size + 1)); // 修正括号避免优先级错误
    if (ptr == NULL)
        return (NULL);
    while (s1[i])
    {
        ptr[i] = s1[i];
        i++;
    }
    ptr[i] = '\0';
    return (ptr);
}

int ft_strlen(const char *str)
{
    int i;

    i = 0;
    while (str[i])
        i++;
    return (i);
}

关键修复说明

  1. get_next_line新增temp_leftover:保存旧的leftover指针,更新后释放原内存块;找到换行符后用ft_strdup复制剩余内容,避免原内存丢失。
  2. ft_read_from_file新增temp_str:调用ft_strjoin后释放旧的leftover内存,解决拼接时的内存泄漏;修正read判断逻辑,区分错误与EOF。
  3. ft_strchr移除BUFFER_SIZE限制:避免长行读取时无法找到换行符。
  4. ft_find_line修正循环条件:确保正确复制到换行符或字符串末尾。
  5. ft_strdup修正malloc括号:避免因运算符优先级导致的内存分配不足。

注意:调用get_next_line时,需由调用者负责释放返回的next_line指针,示例:

char *line;
while ((line = get_next_line(fd)) != NULL)
{
    // 处理line内容
    free(line);
}

内容的提问来源于stack exchange,提问作者Clément

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 07:36:02