I have the following code for a function. It reads a file, line per line, without knowing the size in advance.
It is a learning exercise in my school. I have run the valgrind command on it and I have this output (the full log is here => 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)
I don't know where that could come from. Here is the function that provokes the leak:
#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);
}
The function 'ft_strnew' just mallocs memory for a string and memsets it to 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);
}
Could anybody help me find it? By the way, this is how I call my function in the 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);
}
I free the malloc line (ft_strnew) everytime I call the function, so I am at a loss. If you need more information to help, I'd be glap to provide it. It is my first question on stack, I hope it is clear enough.
Thanks to all of you!
I simply forgot to free the line in the while loop of my main, when returning some values. Adding a couple of free solved my problem! Thanks to all of you!
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);
}
In your ft_strnew function you malloc a new string but you never free it. I would suggest that you free line before returning status in your get_next_line function!