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); }
关键修复说明
get_next_line新增temp_leftover:保存旧的leftover指针,更新后释放原内存块;找到换行符后用ft_strdup复制剩余内容,避免原内存丢失。ft_read_from_file新增temp_str:调用ft_strjoin后释放旧的leftover内存,解决拼接时的内存泄漏;修正read判断逻辑,区分错误与EOF。ft_strchr移除BUFFER_SIZE限制:避免长行读取时无法找到换行符。ft_find_line修正循环条件:确保正确复制到换行符或字符串末尾。ft_strdup修正malloc括号:避免因运算符优先级导致的内存分配不足。
注意:调用get_next_line时,需由调用者负责释放返回的next_line指针,示例:
char *line; while ((line = get_next_line(fd)) != NULL) { // 处理line内容 free(line); }
内容的提问来源于stack exchange,提问作者Clément
相关产品推荐
相关产品推荐

