I did a project where the goal was to read a line of a file at each call of a function(get_nl).
A line is all the characters before a "\n".
I attempted to do it with linked lists to be able to read multiple files at the same time.
But it seems to be leaking memory and I don't really know how or from where. I used valgrind you can check the output just below.
I just used the flag --leak-check=full
==30653== Memcheck, a memory error detector
==30653== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==30653== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==30653== Command: ./a.out
==30653== Parent PID: 20837
==30653==
==30653== Syscall param open(filename) points to unaddressable byte(s)
==30653== at 0x10062D862: open (in /usr/lib/system/libsystem_kernel.dylib)
==30653== by 0x100000D11: main (get_next_line.c:145)
==30653== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==30653==
==30653==
==30653== HEAP SUMMARY:
==30653== in use at exit: 22,577 bytes in 167 blocks
==30653== total heap usage: 188 allocs, 21 frees, 31,025 bytes allocated
==30653==
==30653== 72 bytes in 3 blocks are possibly lost in loss record 26 of 43
==30653== at 0x1000AC6EA: calloc (in /usr/local/Cellar/valgrind/3.15.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==30653== by 0x1007567E2: map_images_nolock (in /usr/lib/libobjc.A.dylib)
==30653== by 0x1007697DA: objc_object::sidetable_retainCount() (in /usr/lib/libobjc.A.dylib)
==30653== by 0x100007C64: dyld::notifyBatchPartial(dyld_image_states, bool, char const* (*)(dyld_image_states, unsigned int, dyld_image_info const*), bool, bool) (in /usr/lib/dyld)
==30653== by 0x100007E39: dyld::registerObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*)) (in /usr/lib/dyld)
==30653== by 0x10022171D: _dyld_objc_notify_register (in /usr/lib/system/libdyld.dylib)
==30653== by 0x100756075: _objc_init (in /usr/lib/libobjc.A.dylib)
==30653== by 0x1001ABB34: _os_object_init (in /usr/lib/system/libdispatch.dylib)
==30653== by 0x1001ABB1B: libdispatch_init (in /usr/lib/system/libdispatch.dylib)
==30653== by 0x1000BA9C2: libSystem_initializer (in /usr/lib/libSystem.B.dylib)
==30653== by 0x100019AC5: ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==30653== by 0x100019CF5: ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==30653==
==30653== LEAK SUMMARY:
==30653== definitely lost: 0 bytes in 0 blocks
==30653== indirectly lost: 0 bytes in 0 blocks
==30653== possibly lost: 72 bytes in 3 blocks
==30653== still reachable: 200 bytes in 6 blocks
==30653== suppressed: 22,305 bytes in 158 blocks
==30653== Reachable blocks (those to which a pointer was found) are not shown.
==30653== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==30653==
==30653== For lists of detected and suppressed errors, rerun with: -s
==30653== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 12 from 12)
Here's my code below :
My helper functions :
#include "header.h"
char *ft_strchr(const char *s, int c)
{
size_t i;
i = 0;
while (s[i] != c)
{
if (!(s[i]))
return (NULL);
i++;
}
return ((char *)s + i);
}
size_t ft_strlen(const char *s)
{
size_t i;
i = 0;
while (s[i])
i++;
return (i);
}
size_t ft_strnlen(const char *s, size_t len)
{
size_t i;
i = 0;
while (i < len && *s)
i++;
return (i);
}
void ft_strdel(char **alst)
{
free(*alst);
*alst = NULL;
}
char *ft_strndup(const char *s, size_t n)
{
char *str;
size_t i;
i = -1;
if (!(str = (char *)malloc(sizeof(char) * ft_strnlen(s, n) + 1)))
return (NULL);
while (++i < n)
str[i] = s[i];
str[i] = '\0';
return (str);
}
My core functions
#include "header.h"
#include <fcntl.h>
void *ft_memalloc(size_t size)
{
char *str;
size_t i;
i = 0;
if (!(str = (char *)malloc(sizeof(char) * (size))))
return (NULL);
while (i < size)
{
str[i] = 0;
i++;
}
return (str);
}
t_list *ft_is_allocated(t_list **alst, const int fd)
{
t_list *temp;
if (!(*alst))
{
if (!((*alst) = ft_memalloc(sizeof(t_list))))
return (NULL);
(*alst)->fd = fd;
}
temp = (*alst);
while (temp->next != NULL && temp->fd != fd)
temp = temp->next;
if (temp->next == NULL && temp->fd != fd)
{
if (!(temp->next = ft_memalloc(sizeof(t_list))))
return (NULL);
temp->next->fd = fd;
temp = temp->next;
temp->next = NULL;
}
return (temp);
}
int ft_newline(char **str, char **line, int r)
{
char *pos;
char *tmp;
size_t i;
if (*str == NULL && r == 0)
return (0);
if ((pos = ft_strchr((*str), '\n')) == NULL && r == 0 && *str)
{
if (ft_strlen(*str) == 0)
{
*line = ft_strndup("", 0);
return (0);
}
if (!(*line = ft_strndup((*str), ft_strlen(*str))))
return (-1);
ft_strdel(str);
return (0);
}
i = (pos - *str);
if (!(*line = ft_strndup((*str), i))
|| !(tmp = ft_strndup(&(*str)[i + 1], ft_strlen(&(*str)[i + 1]))))
return (-1);
free((*str));
(*str) = tmp;
return (1);
}
char *ft_strjoin(char const *s1, char const *s2, int tofree)
{
char *s;
size_t i;
size_t j;
size_t size;
i = -1;
j = -1;
if (s1 == NULL || s2 == NULL)
return (NULL);
size = ft_strlen(s1) + ft_strlen(s2);
if (!(s = (char *)malloc(sizeof(char) * size + 1)))
return (NULL);
while (s1[++i])
s[i] = s1[i];
while (s2[++j])
s[i + j] = s2[j];
s[i + j] = '\0';
if (tofree & 1)
free((char *)s1);
if (tofree & 2)
free((char *)s2);
return (s);
}
int get_nl(int fd, char **line)
{
int r;
char buf[BUFFER_SIZE + 1];
static t_list *head;
if (BUFFER_SIZE < 1 || fd < 0 || read(fd, buf, 0) ||
!(head = ft_is_allocated(&head, fd)) || !line)
return (-1);
while ((r = read(fd, &buf, BUFFER_SIZE)) > 0)
{
buf[r] = '\0';
if (head->tmp == NULL)
head->tmp = ft_strndup(buf, ft_strlen(buf));
else
head->tmp = ft_strjoin(head->tmp, buf, 1);
if (ft_strchr(head->tmp, '\n'))
return (ft_newline(&(head->tmp), line, r));
}
return (ft_newline(&(head->tmp), line, r));
}
int main(int ac, char **av)
{
int fd;
char *line;
int r;
(void) ac;
line = NULL;
r = 0;
fd = open(av[1], O_RDONLY);
r = get_next_line(fd, &line);
free(line);
}
My header file :
#ifndef HEADER_H
# define HEADER_H
# include <stdlib.h>
# include <unistd.h>
# include <stdio.h>
typedef struct s_list
{
int fd;
char *tmp;
struct s_list *next;
} t_list;
t_list *ft_is_allocated(t_list **alst, const int fd);
int ft_newline(char **str, char **line, int r);
int get_nl(const int fd, char **line);
void *ft_memalloc(size_t size);
char *ft_strchr(const char *s, int c);
size_t ft_strlen(const char *s);
size_t ft_strnlen(const char *s, size_t len);
void ft_strdel(char **as);
char *ft_strndup(const char *s, size_t n);
char *ft_strjoin(char const *s1, char const *s2, int tofree);
#endif
EDIT :
I don't know how I got the definitely lost but it doesn't show up anymore and I added the debug flag -g3