Valgrind在我的代码中发现了泄漏,任何人都可以帮我找到它吗?

时间:2017-12-08 17:49:05

标签: c memory-leaks valgrind

我有一个函数的以下代码。 它在不知道大小的情况下读取文件,每行一行。

这是我学校的学习练习。我已经运行了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);
    }

2 个答案:

答案 0 :(得分:1)

在你的ft_strnew函数中,你将malloc一个新的字符串,但你永远不会释放它。 我建议您在get_next_line函数中返回状态前自由行!

答案 1 :(得分:0)

有几种可能性。首先在while循环中,如果您获得status的某些值,则退出时不会释放line_read。这只会导致一个区块丢失。

其次,使用此代码

覆盖*line的值
*line = ft_strcpy(*line, fd_array[fd])

如果您在那里分配更多内存,它看起来是最有可能的候选人。如果您将其更改为该块中的其他位置,则在尝试释放它时会出现完全不同的错误。