Вопрос

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

Мой вопрос заключается в следующем:нужно ли мне освобождать этот указатель до завершения работы функции?

void functionName()
{
 char *variable = (char *) malloc(0);
    //variable is resized with realloc x number of times

 //should free be called here?
 return;
}

Я должен также отметить, что я попытался освободить указатель, однако, gdb предупреждает меня, когда я это делаю.

Это было полезно?

Решение

Да, вы должны освободить его или утерить память. Ваш код должен выглядеть что-то подобное:

void function(void) 
{
    char *variable = (char *)malloc(0);

    variable = realloc(variable, 10);
    // do something with new memory

    variable = realloc(variable, 20);
    // do something with more new memory

    free(variable);  // clean up
}

Призыв malloc(0) Я думаю, немного странно.

Другие советы

Необходимо отметить несколько моментов:

Я не понимаю, как ты используешь realloc() в вашем коде, но если вы используете его таким образом, это неправильно:

variable = realloc(variable, amount);

Когда он не может выделить больше памяти, realloc() ВОЗВРАТ NULL но оставляет исходный указатель неизменным.В приведенной выше строке это означает, что variable является NULL и мы потеряли доступ к памяти, на которую он указывал, но эта память не была освобождена.Правильная идиома такова:

void *tmp = realloc(variable, amount);
if(tmp)
  {
    // success! variable invalid, tmp has new allocated data
    variable = tmp;
  }
else
  {
    // failure! variable valid, but same size as before, handle error
  }

Причина, по которой вы должны использовать второй вариант, заключается в том, что с realloc(), отказ - это плохо, но вполне поправимо во многих ситуациях, в отличие от malloc() где неудача обычно означает "бросить все и умереть".

Это более спорный вопрос, но сомнительно, следует ли вам приводить возвращаемое значение malloc() и realloc() как и ты.Рассмотреть:

// functionally identical in C
char *a = malloc(10);
char *b = (char *)malloc(10);

В C ++ приведение должен быть созданным, потому что в C ++ void * не может быть неявно преобразован в другой тип указателя.(Я думаю, что это языковая ошибка, но не мне судить.) Если ваш код написан на C ++, вы должны использовать new и delete в любом случае.Если ваш код написан на C, но его необходимо скомпилировать с помощью компиляторов C ++ (по какой-то бессмысленной причине), у вас нет выбора, кроме как выполнить приведение.Если вам не нужно компилировать код C с помощью компиляторов C ++ (что аналогично необходимости запускать код Ruby в интерпретаторе Python), перейдите к пунктам ниже, вот почему я думаю, что вам не следует приводить.

  1. В C89, если функция используется без объявления, она будет неявно объявлена как возвращающая int.Если, скажем, мы забыли #include <stdlib.h> и мы позвонили malloc(), версия без приведения вызвала бы ошибку компилятора (неявные приведения из int Для char * не разрешены), в то время как версия с приведением (ошибочно) сообщит компилятору "Я знаю, это звучит безумно, но все равно приведите это". Большинство компиляторов выдадут вам предупреждение о неявных (или несовместимых) объявлениях встроенных функций, таких как malloc(), но актерский состав действительно усложняет поиск.

  2. Допустим, у вас есть какие-то данные:

    float *array = (float *)malloc(10 * sizeof(float));
    

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

    double *array = (double *)malloc(10 * sizeof(double));
    

    Если бы, с другой стороны, вы написали:

    float *array = malloc(10 * sizeof *array);
    

    Вам нужно будет только измениться float Для double на 1 месте.Кроме того, всегда используя sizeof *obj вместо того, чтобы sizeof(type) и никогда не использование приведений означает, что более поздний вызов realloc() может работать без каких-либо изменений, в то время как использование приведений и явных имен типов потребовало бы поиска в любом месте , которое вы вызывали realloc и меняйте слепки , и sizeofs.Также, если вы забудете, сделайте и это:

    double *array = (float *)malloc(10 * sizeof(float));
    

    На большинстве платформ, array теперь это будет только массив из 5 элементов, при условии, что выравнивание не отключено и компилятор не жалуется на то, что вы назначаете float * к a double *.Некоторые считают предупреждение, которое выдает компилятор, полезным, поскольку оно указывает на потенциально неправильные строки.Однако, если мы избегаем sizeof(type) и избегать приведения, мы можем видеть, что линии не будет быть неверными, поэтому привлечение внимания компилятора к ним - пустая трата времени, которое мы могли бы использовать для программирования.

От страницы человека:

Если размер равно 0, то Malloc () возвращает либо NULL, либо уникальное значение указателя, которое позже может быть успешно передано в Free ().

Итак, я верю, что ответ «да» :).

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

Вы должны быть в состоянии просто позвонить free(variable) в конце. Если realloc когда-либо должен переместить данные, чтобы изменить его, это называет free Внутренне, вам не нужно беспокоиться об этом.

Кроме того, где вы инициализировать variable, вы могли бы просто установить это NULL вместо звонка malloc; realloc будет работать так же, как malloc первый раз.

Посмотрите на некоторые ответы, которые я дал пару вопросов в отношении управления памятью:

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

Надеюсь, это поможет, наилучшие пожелания, Том.

int main(int argc, char *argv[])
{
        char *p = malloc(sizeof(argv[1]));

        p = argv[1];
        printf("%s\n", p);
        free(p);
        return 0;
}

IAM получил ошибку Glibc

hello
*** glibc detected *** ./a.out: munmap_chunk(): invalid pointer: 0x00007fff66be94c6 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7f38dca1db96]
./a.out[0x4005ed]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7f38dc9c076d]
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top