Как освободить указатель, возвращаемый функцией?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char* f(void) {
  char *x;
  x = malloc(sizeof(char) * 4);
  strcpy(x, "abc");
  return(x);
}

int main(void) {
  char *a;
  a = f();
  printf("%s", a);
  free(a);
  return(0);
}

Нужно ли освобождать переменную x в функции? Если да, то как это возможно, когда мне нужно вернуть его?

Ответ 1

Нужно ли освобождать переменную x в функции?

Да (см. мой более поздний комментарий). Для каждого вызова malloc требуется более поздний вызов free. В противном случае у вас есть утечка. Помните, хотя; вы не "свободны [ing] x", вы освобождаете память, на которую ссылается x.

Когда вы возвращаете x, копия значения (адреса) x производится и возвращается вызывающему. x был объявлен с автоматическим временем хранения. Это память, на которую она ссылается, должна быть освобождена.

Если так, то как это возможно, когда мне нужно его вернуть.

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

Лучшим подходом (IMO) является выбор буфера в качестве входного параметра. Теперь очень ясно, кто несет ответственность за управление этой памятью (то есть вызывающей стороной). Возможно, я даже не хочу динамически выделять его. С этим дизайном это мой выбор.

void f(char *buf, size_t buf_size) {
  strncpy(buf, "abc", buf_size - 1);
  buf[buf_size-1] = '\0';
}

На боковой ноте вы всегда должны проверять возвращаемое значение malloc. Он может выйти из строя, и в этом случае возвращается нулевой указатель. Кроме того, sizeof(char) гарантируется 1 стандартом, поэтому вы можете удалить этот бит и просто сказать malloc(n).

Ответ 2

Да, он должен быть освобожден вызывающим абонентом. Например, free в вашем основном.

Когда вы возвращаете x в функции f, копия адреса возвращается обратно вызывающему. Вызывающий абонент может вызывать free по этому адресу.

Ответ 3

Да, вам нужно освободить, но он уже освобождается, когда вы выполняете free(a); в main (так как a присваивается равному x в строке a = f();).

Ответ 4

x уничтожается после выхода из функции. Значение x - это адрес, который указывает на динамически выделенный объект. Объект все еще существует после выхода из функции.

Чтобы освободить динамический объект, вы должны передать значение x, возвращаемое функцией f, в функцию free.

Ответ 5

Когда вы вызываете malloc, он выделяет память и возвращает начальный адрес этого блока памяти.

В вашем случае вы возвращаете этот адрес обратно вызывающему, теперь вызывающий, главный, несет ответственность за его освобождение.

Единственное, что требуется для освобождения блока памяти - это начальный адрес, AFIK OS отвечает за выделение/освобождение памяти, он использует довольно сложные алгоритмы, но программам нужно только отслеживать исходный адрес памяти. Этот адрес может быть сохранен или перемещен так же, как и любое другое целочисленное значение, потому что в 32-битных системах это всего лишь значение int.

Ответ 6

У вас хорошо работает код, вы освободили a, который является строкой, разделенной на f.