Что является хорошей практикой для освобождения памяти, когда функция копирует аргумент, переданный указателем? - PullRequest
0 голосов
/ 19 июня 2020

Если функция копирует содержимое аргумента, переданного указателем, чтобы сделать данные, которые она содержит, доступными только «внутри», но этот параметр заполняется вызовом функции, выделяющей элементы в куче и возвращающей указатель для них это вызовет утечку памяти, поскольку отправляемому выражению не будет присвоена никакая переменная. См. Этот пример:

struct my_struct_s
{
    char *msg;
};

struct my_struct_s *make_struct(char *msg)
{
    struct my_struct_s *res = malloc(sizeof *res);
    if (res == NULL)
        return NULL;

    res->msg = strdup(msg); // I make a copy
    if (res->msg == NULL)
    {
        free(res);
        return NULL;
    }
    return res;
}

void release(struct my_struct_s **my_struct)
{
    if (*my_struct == NULL)
        return;
    free((*my_struct)->msg);
    free(*my_struct);
}

int main()
{
    // char *str = strdup("Hello, world!");
    // struct my_struct_s *my_struct = make_struct(str);
    struct my_struct_s *my_struct = make_struct(strdup("Hello, world!"));
    release(&my_struct);
    // free(str);
    return 0;
}

Закомментированный код представляет версию этой программы без утечки памяти (я думаю), потому что у нас есть переменная (str), к которой позже можно получить доступ для выпуска, в то время как код без комментариев вызовет утечку памяти, потому что мы не контролируем выделенную память.

Поле msg доступно, потому что тело структуры объявлено здесь в том же файле, но предположим, что он определен в файле реализации, поэтому он не будет доступен извне без прохождения функции.

В такой ситуации, каковы лучшие практики, чтобы избежать памяти утечки? Создать переменную, которая будет выпущена позже, как в закомментированном коде, или не делать копию в функции, что потенциально усложняет управление кодом?

...