Почему у меня возникает утечка памяти при вызове malloc () для создания узла для связанного списка? - PullRequest
0 голосов
/ 05 апреля 2019

Я студент, и в настоящее время я работаю над графическим проектом, в котором я читаю файл, содержащий числа, где их положение в файле определяет координаты, а значение определяет высоту. Например:

1 0 0 -1 -1 0 1 1 0 0

-1 0 0 0 1 0 0 0 0 0

-1 1 0 0 -1 1 0 0 0 1

когда x = 0, y = 0, тогда z = 1

когда x = 1, y = 0, тогда z = 0

и т.д.

Я написал код, и он отлично работает. Я построчно читаю файл и сохраняю строку в char** указателе с именем tab, где каждое значение *tab содержит каждое значение одной строки. Вместо создания 2d массива я сохранил каждую строку в связанном списке. Причина, по которой я это сделал, заключается в том, что у меня уже был код, который читает строку за строкой, и код, разделяющий строку, возвращающий char **.

Но у меня есть утечки памяти. Чтобы найти эти утечки, я компилирую все файлы .c с помощью gcc, используя флаг -g, а затем использую команды LLDB и Leaks в OSX. Я отлаживаю код, выполняя код шаг за шагом. Вот что я получил от LLDB:

(lldb) n
Process 20739 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = step over
    frame #0: 0x0000000100001d66 fdf`ft_new(tab=0x0000000100207530) at ft_lst_gnl.c:22
   19       node = NULL;
-> 20       if (!(node = (t_gnl *)malloc(sizeof(t_gnl))))
   21           return (NULL);
   22       node->tab = tab;
   23       node->next = NULL;
   24       return (node);
   25   }

Перед выполнением строки 20 у меня нет утечки:

Date/Time:       2019-04-05 17:13:34.357 +0200
Launch Time:     2019-04-05 17:13:15.974 +0200
OS Version:      Mac OS X 10.12.6 (16G29)
Report Version:  7
Analysis Tool:   /Applications/Xcode.app/Contents/Developer/usr/bin/leaks
Analysis Tool Version:  Xcode 9.2 (9C40b)
----

leaks Report Version:  2.0
Process 24286: 607 nodes malloced for 66 KB
Process 24286: 0 leaks for 0 total leaked bytes.

Но в тот момент, когда я выполняю эту строку, вывод команды Leaks изменяется:

leaks Report Version:  2.0
Process 24286: 608 nodes malloced for 66 KB
Process 24286: 1 leak for 16 total leaked bytes.
Leak: 0x100400100  size=16  zone: DefaultMallocZone_0x1000b2000
    0x00000000 0x00000000 0x00000000 0x00000000     ................

Вот моя структура t_gnl:

typedef struct  s_gnl
{
    char            **tab;
    struct s_gnl    *next;
}               t_gnl;

Я провел сравнение с тестовым кодом, где использовал malloc для создания другого связанного списка или строки, и я протестировал его с помощью метода отладки (команда LLDB + Leaks), и строки, содержащие malloc (), не пропускали.

Спасибо за чтение.

РЕДАКТИРОВАТЬ: Вот немного моего кода. Я могу добавить больше, но я боюсь, что это будет слишком много и запутанно.

char **ft_strsplit(char const *s, char c);

t_gnl   *ft_store(char *file, t_gnl **list, t_env **fdf)
{
    int     fd;
    char    *line;
    int     height;
    int     ret;

    fd = open(file, O_RDONLY);
    if (fd < 0)
        return (NULL);
    height = 0;
    while ((ret = get_next_line(fd, &line)))
    {
        if (ret == -1)
            break ;
        ft_append(list, ft_strsplit(line, ' '));
        height++;
        ft_strdel(&line);
    }
    if (line)
        ft_strdel(&line);
    if (ret == -1 || *list == NULL)
    {
        close(fd);
        return (NULL);
    }
    *fdf = ft_init_env(*list, height);
    close(fd);
    return (*list);
}

static t_gnl    *ft_new(char **tab)
{
    t_gnl   *node;

    //node = NULL;
    if (!(node = (t_gnl *)malloc(sizeof(t_gnl))))
        return (NULL);
    node->tab = tab;
    node->next = NULL;
    return (node);
}

void            ft_append(t_gnl **head, char **tab)
{
    t_gnl   *list;
    t_gnl   *elem;

    elem = NULL;
    elem = ft_new(tab);
    if (*head != NULL)
    {
        list = *head;
        while (list->next)
            list = list->next;
        list->next = elem;
    }
    else
        *head = elem;
}

int main(int ac, char **av)
{
    t_gnl   *list;
    t_env   *fdf;

    list = NULL;
    fdf = NULL;
    list = ft_store(av[1], &list, &fdf);
    if (fdf == NULL || ft_error(&list, fdf->map->width))
    {
        ft_putstr("Error\n");
        exit(0);
    }
    ft_fdf(list, fdf);
}

PS: Извините, если я сделал несколько грамматических ошибок, я француз. Если что-то недостаточно ясно, я могу попытаться дать лучшее объяснение. Кроме того, это мой первый пост в Stackoverflow, поэтому я могу забыть некоторую информацию.

...