Malloc错误:已释放对象的校验和不正确-对象可能在释放后被修改

时间:2018-08-10 16:16:56

标签: c memory memory-management memory-leaks malloc

我已经尝试修复了2天。我真的不明白发生了什么。

我编写了一个函数来从文件行中逐行读取。它称为 get_next_line()。这是一个学校项目,只允许使用我自己的C库以及 read() malloc() free() >。

Here is a link to the full GitHub repo,包括说明。最后,我只能提交 get_next_line.c get_next_line.h

基本上,如果不处理内存泄漏,我的程序似乎可以正常运行。当我开始使用 ft_strdel()函数修复泄漏时,我的程序对于大多数测试用例仍然可以正常运行。

void    ft_strdel(char **as)
{
    if (!as || !*as)
        return ;
    free(*as);
    *as = 0;
}

但是,如果我通过学校通过的高级单元测试,则会遇到不同的错误。有时候它们似乎随机出现,因为我可以连续3次通过并且第四次出现malloc错误。

当前版本似乎可以处理所有内存泄漏。因此,我在filechecker中遇到此错误:

  

get_next_line_tests(43165,0x7fff9e83d340)malloc: *   对象0x7fe0e3403748的错误:释放的对象的校验和不正确-   对象在释放后可能已被修改。   * 在malloc_error_break中设置一个断点进行调试


这是完整功能:

#include "get_next_line.h"

static t_list   *get_current_node(const int fd, t_list **line_list)
{
    t_list      *tmp;

    tmp = *line_list;
    while (tmp)
    {
        if ((int)tmp->content_size == fd)
            return (tmp);
        tmp = tmp->next;
    }
    return (NULL);
}

static t_list   *create_new_node(int fd, t_list **line_list)
{
    t_list  *new;

    new = ft_lstnew("\0", fd);
    ft_lstadd(line_list, new);
    return (new);
}

char            *read_until_newline(int fd)
{
    char    buf[BUFF_SIZE + 1];
    char    *tmp;
    char    *stack;
    int     ret;

    if (read(fd, buf, 0) < 0)
        return (NULL);
    stack = ft_strnew(1);
    if (!stack)
        return (NULL);
    while ((ret = read(fd, buf, BUFF_SIZE)) > 0)
    {
        buf[ret] = '\0';
        tmp = ft_strjoin(stack, buf);
        ft_strdel(&stack);
        stack = tmp;
        if (ft_strchr(buf, '\n'))
            break;
    }
    return (stack);
}

int             get_index_newline(char *str)
{
    int     i;

    i = 0;
    while (str[i] && str[i] != '\n')
        i++;
    return (i);
}

int     get_next_line(const int fd, char **line)
{
    static t_list   *line_list;
    t_list          *current;
    char            *buffer;
    char            *tmp;
    int             index_newline;

    if (fd < 0 || line == NULL)
        return (-1);
    current = get_current_node(fd, &line_list);
    if (!current)
        current = create_new_node(fd, &line_list);
    if (!ft_strchr(current->content, '\n'))
        buffer = read_until_newline(fd);
    else
        buffer = ft_strnew(1);
    if (!buffer)
        return (-1);
    if (!ft_strlen(buffer) && !ft_strlen(current->content))
        return (0);
    tmp = current->content;
    current->content = ft_strjoin(tmp, buffer);
    if (tmp)
        ft_strdel(&tmp);
    if (buffer)
        ft_strdel(&buffer);
    index_newline = get_index_newline(current->content);
    *line = ft_strsub(current->content, 0, index_newline);
    tmp = current->content;
    current->content = ft_strsub(tmp, index_newline + 1, ft_strlen(tmp) - index_newline - 1);
    if (tmp)
        ft_strdel(&tmp);
    return (1);
}

请随时对我在代码中可能遇到的任何初学者错误发表评论。但是请注意,我必须遵循一定的规范,以解释我的变量声明和初始化。我不能使用 for 循环。并且有很多类似的限制。

使用 if 语句保护我的 ft_strdel()调用是我最后解决此问题的意图,显然它失败了,而且没有用。

编辑:

我使用静态链接列表处理多个 fd 。每个节点都包含一个带有最后一个读取缓冲区的字符串(减去最近读取的行后,从读取中剩下的所有内容)。每个节点都包含一个int来存储从中读取的 fd 。这样,我便遍历列表,直到找到对应的 fd 来检查先前的阅读内容。如果未返回任何节点,则意味着我没有为特定的fd存储任何内容,因此我将创建一个新节点。

希望您有答案!我不是Stack Overflow的普通用户,我尽力格式化帖子并保持具体。告诉我是否需要编辑某些内容。

感谢您的帮助!

0 个答案:

没有答案