2015-04-15 3 views
10

Я создал функцию, предназначенную для ввода пользователем. Он требует, чтобы память была назначена переменной, содержащей вход пользователя; однако эта переменная возвращается в конце функции. Каков правильный способ освободить выделенную память/вернуть значение переменной?Правильный способ свободной памяти возвращенной переменной

Вот код:

char *input = malloc(MAX_SIZE*sizeof(char*)); 
int i = 0; 
char c; 

while((c = getchar()) != '\n' && c != EOF) { 
    input[i++] = c; 
} 

return input; 

Должен ли я вернуть адрес входа и освободить его после того, как она используется?

Любопытно, как правильно выбрать входную переменную.

+0

Если вы 'malloc', в конечном итоге кому-то понадобится' free', будь то вы в другом api или вызывающем. Связанный, если поддерживается на вашей целевой платформе (-ах), ['getline'] (http://pubs.opengroup.org/stage7tc1/functions/getdelim.html), функция библиотеки, добавленная в POSIX.1-2008, * почти * делать то, что вы пытаетесь реализовать. Он по-прежнему требует, чтобы вызывающий пользователь в конечном итоге «освобождал» любые возвращенные распределения, но также предоставляет семантику повторного использования, где ваш код делает * not *. В зависимости от предполагаемого использования и целевой платформы (ей) это может быть целесообразно рассмотреть. – WhozCraig

ответ

11

Это довольно просто, если вы переходите на free() тот же указатель, возвращаемый malloc(), это нормально.

Например

char *readInput(size_t size) 
{ 
    char *input; 
    int chr; 
    input = malloc(size + 1); 
    if (input == NULL) 
     return NULL; 
    while ((i < size) && ((chr = getchar()) != '\n') && (chr != EOF)) 
     input[i++] = chr; 
    input[size] = '\0'; /* nul terminate the array, so it can be a string */ 
    return input; 
} 

int main(void) 
    { 
    char *input; 
    input = readInput(100); 
    if (input == NULL) 
     return -1; 
    printf("input: %s\n", input); 
    /* now you can free it */ 
    free(input); 
    return 0; 
    } 

То, что вы никогда не должны делать что-то вроде

free(input + n); 

потому input + n не возвращается указатель на malloc().

Но ваш код, есть и другие вопросы, вы должны заботиться о

  1. Вы выделение места для MAX_SIZEchar с, так что вы должны умножить на sizeof(char), который 1, вместо sizeof(char *), который будет выделять MAX_SIZE указателей, а также вы можете сделать MAX_SIZE параметр функции, потому что если вы назначаете фиксированный буфер, вы можете определить массив в main() размером MAX_SIZE, например char input[MAX_SIZE], и передать его readInput() в качестве параметра r, что позволяет избежать malloc() и free().

  2. Вы выделяете столько места, но не мешаете переполнению цикла while, вы должны убедиться, что i < MAX_SIZE.

+0

Он не может использовать локальные массивы, поскольку, когда он возвращается, и кадр стека функции будет уничтожен, не будет никакого способа гарантировать, что массив будет целым. Компилятор даст вам предупреждение: «Функция возвращает адрес локальной переменной [-Wreturn-local-addr]». Кроме этого, хороший ответ. –

+1

@EnzoFerber Я имел в виду передать массив функции и заполнить ее там, я знаю, что вы не должны возвращать локальный массив. Думаю, мне нужно это разъяснить. –

4

Вы могли бы написать функцию с возвращаемым типом char*, возвращение input, и попросить пользователя позвонить free, когда их сделали с данными.

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

-1

Это классический кейс. Функция mallocs для своего результата, вызывающий должен освободить возвращаемое значение. Теперь вы ходите по тонкому льду утечек памяти. 2 причины

Первый; вы не можете передавать свободное требование принудительно (т. е. компилятор или время выполнения не могут помочь вам - контрастировать с указанием типов аргументов).Вам просто нужно документировать его где-то и надеяться, что вызывающий абонент прочитает ваши документы.

Во-вторых: даже если вызывающий абонент знает, что может освободить результат, он может совершить ошибку, будет принят некоторый путь ошибки, который не освободит память. Это не вызывает немедленной ошибки, похоже, что все работает, но после запуска в течение 3 недель ваше приложение вылетает из-за нехватки памяти

Вот почему так много современных языков сосредоточены на этой теме, умных указателях C++, Java, C# и т. Д. Сбор мусора, ...