Valgrind 在我的代码中发现了漏洞,有人可以帮我找到吗?

Valgrind finds a leak in my code, could anybody help me find it?

我有以下功能代码。 它读取一个文件,一行一行,事先不知道大小。

这是我学校的一次学习活动。我有 运行 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)] = '[=11=]';
    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 != '[=11=]') && (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] != '[=11=]')
        *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'只是为字符串分配内存并将其设置为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)'[=12=]', (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);
    }

在您的 ft_strnew 函数中,您 malloc 了一个新字符串,但您从未释放它。 我建议您在 get_next_line 函数中返回状态之前释放一行!

有两种可能性。首先,在你的 while 循环中,如果你得到 status 的特定值,你会在不释放 line_read 的情况下退出。不过,这只会导致丢失一个区块。

其次,你用这段代码覆盖*line的值

*line = ft_strcpy(*line, fd_array[fd])

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