2016-04-28 4 views
1

Что это правильный способ освободить память в этом случае; есть ли разница между этими двумя методами?Свободная память в функции

void allocateArray1(int size, int value) 
{ 
    int* arr = malloc(size * sizeof(int)); 
    /* ... */ 
    free(arr); 
} 

int* allocateArray2(int size, int value) 
{ 
    int* arr = malloc(size * sizeof(int)); 
    /* ... */ 
    return arr; 
} 

int main() 
{ 
    int* vector = allocateArray2(5,45); 
    free(vector); 
    allocateArray1(5,45); 

    return 0; 
} 
+0

Очевидно, что есть разница. В 'allocateArray1()' ваша функция 'main()' никогда не видит или не знает о массиве и поэтому ничего не может с этим поделать. Используйте этот метод, когда это именно то, чего вы хотите, чтобы 'main()' быть не в состоянии сделать. –

+0

Обратите внимание, что 'malloc' и' free' * не заботятся о том, как работают * ваши * функции. Все, о чем они заботятся, это то, что память, выделенная с помощью 'malloc', в конечном итоге освобождается с помощью' free'. – immibis

+0

не имеет значения, какой из них вы выберете, если 'main' не имеет никакого бизнес-обмена с выделенной вами памятью, просто выделите и освободите его в рамках вызываемой функции. –

ответ

3

Они эквивалентны, так как распределение с malloc и релиз free. Метод allocateArray1 делает все это в одной функции, что облегчает запоминание памяти. Но иногда вам нужна функция для предоставления основной (или некоторой другой функции) памяти, поэтому она может ее использовать. В этом случае вам просто нужно будет удалить его позже, как в методе allocateArray2.

1

Это иногда то, что известно как “ семантики собственности ”, то есть кто владеет объект (и, следовательно, кто несет ответственность за освобождение объекта).

Некоторые функции требуют, чтобы вызывающий абонент освободил возвращенный объект, например. strdup(), или иногда функция POSIX getline(). В этих случаях функции strdup() и getline() не могут знать, что вы планируете делать с результатом или как долго вам понадобится результат, поэтому они делегируют задачу освобождения объекта вызывающей функции.

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

При разработке проекта важно иметь последовательную семантику собственности. Например, возможно, любая функция, которая делегирует задачу освобождения объектов, может начинаться с alloc (или new или create и т. Д.), И тогда вы всегда будете знать, что освобождение результата этих функций является вашей ответственностью. На самом деле не важно, как определяется семантика собственности, если они согласованы.

0

Какой именно способ освободить память в этом случае; есть ли разница между этими двумя методами?

Оба метода верны.

Однако я предпочту использовать функцию int* allocateArray2(int size, int value), которая выделяет некоторую память из кучи внутри функции и возвращает указатель на выделенное пространство памяти. Основная причина, по которой требуется malloc, - это когда у вас есть данные, которые должны иметь срок службы, отличный от области кода. Ваш код вызывает malloc в одной подпрограмме, где-то хранит указатель и в конечном итоге вызывает вызов в другой процедуре.

void allocateArray1(int size, int value) Функция, которая запрашивает некоторую память, выполняет некоторую обработку и освобождает память перед возвратом, не является эффективным методом, если size меньше. Вместо этого вы можете создать массив в стеке и использовать его для дальнейшей обработки. Преимущество использования стека для хранения переменных - это то, что память управляется для вас. Вам не нужно выделять память вручную или освобождать ее, как только она вам больше не понадобится. Более того, поскольку процессор так эффективно организует стекную память, чтение и запись в стек переменных очень быстро. Однако это может привести к переполнению стека, если вы попытаетесь выделить больше памяти в стеке, чем это подходит, например, создав слишком большие переменные массива.

Пример очень большой переменной стека в C:

int foo() 
{ 
    double x[1048576]; 
} 

Заявленная массив потребляет 8 Mebibytes данных (предполагается, что каждый двойной 8 байт); если это больше памяти, чем доступно в стеке (в соответствии с параметрами создания потока или ограничениями операционной системы) произойдет переполнение стека.

Смежные вопросы