Home > database >  Memory leak in C with static variable and i dont know how to fix it
Memory leak in C with static variable and i dont know how to fix it

Time:02-03

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.

  • Related