我有一个函数的以下代码。 它在不知道大小的情况下读取文件,每行一行。
这是我学校的学习练习。我已经运行了valgrind命令,我有这个输出(完整的日志在这里=> valgrind log):
==21166== 44 bytes in 1 blocks are definitely lost in loss record 14 of 42
==21166== at 0x1000CB606: malloc (in /Users/cbaillat/.brew/Cellar/valgrind/3.13.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==21166== by 0x100000F0C: ft_strnew (in ./get_next_line)
==21166== by 0x10000061C: get_next_line (get_next_line.c:71)
==21166== by 0x10000058A: main (main.c:31)
我不知道那可能来自哪里。这是引发泄漏的功能:
#include "get_next_line.h"
/*
** If newline is null, it means it hasn't found a new line in the string.
** It means we have reach the end of line.
*/
static int ft_copy_leftover(char **line, char fd_buffer[BUFF_SIZE], char *nl)
{
if (nl == NULL)
return (1);
ft_strcpy(fd_buffer, &nl[1]);
(*line)[nl - (*line)] = '\0';
return (1);
}
/*
** 1- We keep reading unless we find a new line or we reach the end of file
** 2- We reallocate the old pointer with buffer size
** 3- As long as there are characters to read and we haven't encountered a
** new line, we keep copying the data into line
** We store the buffer in line, and then erase it
** 4- If we have already reached the end of file, we do not need to copy the
** buffer. Otherwise we copy it to line.
*/
static int read_line(const int fd, char fd_buffer[BUFF_SIZE], char **line)
{
int32_t status;
char *newline;
uint32_t len;
while (((newline = ft_strchr(*line, '\n')) == NULL)
&& ((status = read(fd, fd_buffer, BUFF_SIZE)) > FILE_READ))
{
len = ft_strlen(*line) + 1;
if ((*line = ft_realloc(*line, len, len + BUFF_SIZE)) == NULL)
return (ERROR);
ft_strcat(*line, fd_buffer);
ft_bzero(fd_buffer, BUFF_SIZE);
}
if ((**line != '\0') && (status >= FILE_READ))
return (ft_copy_leftover(line, fd_buffer, newline));
return (status);
}
/*
** 1- If the buffer is not empty, we allocate a new string and copy the buffer
** contents
** 2- We loop in the buffer in case we have multiple new lines inside
*/
int get_next_line(const int fd, char **line)
{
static char fd_array[ULIMIT_N][BUFF_SIZE + 1];
int8_t status;
if (fd < 0 || fd > ULIMIT_N || line == NULL
|| !(*line = ft_strnew(BUFF_SIZE + 1)))
return (ERROR);
if (fd_array[fd][0] != '\0')
*line = ft_strcpy(*line, fd_array[fd]);
ft_bzero(fd_array[fd], BUFF_SIZE + 1);
status = read_line(fd, fd_array[fd], line);
return (status);
}
函数'ft_strnew'只是mallocs字符串的内存并将其存储为0:
#include "libft.h"
char *ft_strnew(size_t size)
{
char *str;
if ((str = (char *)malloc(sizeof(*str) * (size + 1))) == NULL)
return (NULL);
ft_memset((void *)str, (int)'\0', (size + 1));
return (str);
}
有人可以帮我找到它吗? 顺便说一句,这就是我在main中调用我的函数的方式:
int main(int ac, char **av)
{
int32_t i;
int32_t fd;
int32_t status;
char *line_read;
if (ac <= 1)
return (0);
fd = open(av[1], O_RDONLY);
i = 0;
line_read = NULL;
while (1)
{
status = get_next_line(fd, &line_read);
// printf("status: %d\n", status);
if (status == ERROR)
return (ERROR);
if (status == FILE_READ)
return (SUCCESS);
ft_putstr(line_read);
free (line_read);
}
return (SUCCESS);
}
每次调用函数时我都会释放malloc行(ft_strnew),所以我不知所措。如果您需要更多信息来帮助我,我会很乐意提供它。这是我关于堆栈的第一个问题,我希望它足够清楚。
感谢大家!
当我返回一些值时,我只是忘了在main的while循环中释放该行。添加几个免费解决了我的问题!谢谢你们所有人!
while (1)
{
status = get_next_line(fd, &line_read);
// printf("status: %d\n", status);
if (status == ERROR)
{
free (line_read);
return (ERROR);
}
if (status == FILE_READ)
{
free (line_read);
return (SUCCESS);
}
ft_putstr(line_read);
free (line_read);
}
答案 0 :(得分:1)
在你的ft_strnew函数中,你将malloc一个新的字符串,但你永远不会释放它。 我建议您在get_next_line函数中返回状态前自由行!
答案 1 :(得分:0)
有几种可能性。首先在while
循环中,如果您获得status
的某些值,则退出时不会释放line_read
。这只会导致一个区块丢失。
其次,使用此代码
覆盖*line
的值
*line = ft_strcpy(*line, fd_array[fd])
如果您在那里分配更多内存,它看起来是最有可能的候选人。如果您将其更改为该块中的其他位置,则在尝试释放它时会出现完全不同的错误。