Если функция копирует содержимое аргумента, переданного указателем, чтобы сделать данные, которые она содержит, доступными только «внутри», но этот параметр заполняется вызовом функции, выделяющей элементы в куче и возвращающей указатель для них это вызовет утечку памяти, поскольку отправляемому выражению не будет присвоена никакая переменная. См. Этот пример:
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
доступно, потому что тело структуры объявлено здесь в том же файле, но предположим, что он определен в файле реализации, поэтому он не будет доступен извне без прохождения функции.
В такой ситуации, каковы лучшие практики, чтобы избежать памяти утечки? Создать переменную, которая будет выпущена позже, как в закомментированном коде, или не делать копию в функции, что потенциально усложняет управление кодом?