As an exercise i'm writing a C function to read content from a file descriptor one line at a time. In the exercise i'm only allowed to use read(), malloc() and free() from the standard library, while using one static variable. The function works but i keep getting a persistent memory leak when i reach the last line in the file that i cant seem to solve.
Leak:
Direct leak of 1 byte(s) in 1 object(s) allocated from:
#0 0x7f37f253a4bf in __interceptor_malloc (/usr/lib/gcc/x86_64-pc-linux-gnu/12/libasan.so.8 0xbd4bf)
#1 0x5644d5df4735 in offset /home/practical/Documents/Code/42/get_next_line/get_next_line.c:71
#2 0x5644d5df49ba in get_next_line /home/practical/Documents/Code/42/get_next_line/get_next_line.c:116
#3 0x5644d5df4a8b in main /home/practical/Documents/Code/42/get_next_line/get_next_line.c:138
#4 0x7f37f22cd189 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
SUMMARY: AddressSanitizer: 1 byte(s) leaked in 1 allocation(s).
Code:
#include "get_next_line.h"
#include <stdlib.h>
#include <unistd.h>
// needed for main:
#include <stdio.h>
#include <fcntl.h>
// finds the first line ending in \n from buffer
// this is the line for get_next_line to return
char *next_line(char *a)
{
int i;
char *buf;
if (!a || !a[0])
return (NULL);
i = 0;
while (a[i] && a[i] != '\n')
i ;
if (a[i] == '\n')
i ;
buf = (char *)malloc((sizeof(char) * i) 1);
if (!buf)
return (NULL);
i = 0;
while (a[i] && a[i] != '\n')
{
buf[i] = a[i];
i ;
}
if (a[i] == '\n')
buf[i ] = '\n';
buf[i] = '\0';
return (buf);
}
// finds the end of the line we just returned in the buffer
// moves it to the end of new buffer
// changes the \n before it to '\0', so our new buffer does not contain it
// this offsets our buffer, the buffer now starts
// at the next line to be printed
char *offset(char *a)
{
char *buf;
int i;
int x;
i = 0;
x = 0;
while (a[i] && a[i] != '\n')
i ;
if (a[i] == '\0')
{
free(a);
return (NULL);
}
if (a[i] == '\n')
i ;
buf = (char *)malloc(ft_strlen(a) - i 1);
if (!buf)
return (NULL);
while (a[i x])
{
buf[x] = a[i x];
x ;
}
buf[x] = '\0';
free(a);
return (buf);
}
// static buffer str starts at the next line to be printed
// we use strchr to find if there is a \n in the buffer
// if theres not, we read from the file into the buffer
// if \n is present, this is the line to print
// next_line then gets the first line ending in '\n' from the static buffer
// we return this line
// then we offset the static buffer by the line we just returned
char *get_next_line(int fd)
{
static char *str;
char *buf;
int i;
if (fd < 0 || BUFFER_SIZE <= 0)
return (NULL);
buf = (char *)malloc((sizeof(char) * BUFFER_SIZE) 1);
if (!buf)
return (NULL);
i = 1;
while (!(ft_strchr(str, '\n')) && i != 0)
{
i = read(fd, buf, BUFFER_SIZE);
if (i == -1)
{
free(buf);
return (NULL);
}
buf[i] = '\0';
str = ft_strjoin(str, buf);
}
free(buf);
buf = next_line(str);
str = offset(str);
return (buf);
}
int main(int argc, char *argv[])
{
char *line;
int fd;
if (argc < 2)
{
printf("Usage: %s <file>\n", argv[0]);
return (1);
}
fd = open(argv[1], O_RDONLY);
if (fd == -1)
{
perror("Failed to open file");
return (1);
}
while (line != NULL)
{
line = get_next_line(fd);
printf("%s", line);
free(line);
}
close (fd);
return (0);
}
ft_strjoin
char *ft_strdup(char *src)
{
char *dst;
int i;
i = 0;
dst = malloc(ft_strlen(src) 1);
if (!dst)
return (NULL);
while (src[i])
{
dst[i] = src[i];
i ;
}
dst[i] = '\0';
return (dst);
}
char *ft_strcat(char *dest, char *src)
{
int i;
int l;
i = 0;
l = ft_strlen(dest);
while (src[i] != '\0')
{
dest[i l] = src[i];
i ;
}
dest[i l] = '\0';
return (dest);
}
char *ft_strjoin(char const *s1, char const *s2)
{
char *str;
size_t len;
if (!s1 && !s2)
return (ft_strdup(""));
if (s1 && !s2)
return (ft_strdup((char *)s1));
if (!s1 && s2)
return (ft_strdup((char *)s2));
len = ft_strlen((char *)s1) ft_strlen((char *)s2);
str = malloc(sizeof(char) * (len 1));
if (!str)
return (NULL);
str[0] = '\0';
ft_strcat(str, (char *)s1);
ft_strcat(str, (char *)s2);
return (str);
}
Problem
I went over the code and it seems that i am freeing everything.
I think the issue may be with returning buf
in the get_next_line
function, which gets allocated by the next_line
function. I cant free this because i am returning it, but i am freeing the string later in the main()
.
Maybe i should be freeing the static variable after i reach the end of the file i'm reading from the descriptor?
Any suggestions appreciated, thanks
CodePudding user response:
"seems that i am freeing everything" --> code does not free str
in get_next_line()
when done.