it-roy-ru.com

Правильный способ освободить память возвращаемой переменной

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

Вот код:

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

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

return input;

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

Любопытно, как наиболее подходящий метод для освобождения входной переменной.

13
w m

Это довольно просто, если вы передаете 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_SIZEchars, так что вам нужно умножить на sizeof(char), которая является 1, вместо sizeof(char *), которая будет выделять указатели MAX_SIZE, а также вы можете сделать MAX_SIZE параметром функции вместо этого, потому что если вы выделяете фиксированный буфер, вы можете определить массив в main() с размером MAX_SIZE как char input[MAX_SIZE], и передать его в readInput() в качестве параметра, таким образом избегая malloc() и free().

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

15
Iharob Al Asimi

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

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

4
orlp

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

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

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

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

1
pm100