Realloc просто расширяет память или это может привести к проблемам с памятью? - PullRequest
2 голосов
/ 20 сентября 2011

У меня есть следующий код:

#include <stdio.h>
#include <stdlib.h>
#define OUT

void getDataFromServer(OUT int** array, OUT int* size)
{
    static int tmpArr[] = {0x00, 0x01, 0x02, 0x03,  0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
                        0x10, 0x11, 0x12, 0x13,  0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F};
    *size = sizeof tmpArr / sizeof(int);
    printf("Before realloc: %p\n", *array);
    *array = realloc(*array, sizeof(*array) * *size);
    printf("After realloc : %p\n", *array);
    int i=0;
    for (; i < *size; i++)
    {
        (*array)[i] = tmpArr[i];
    }
}

int main(void)
{
    int size = 0;
    int* dataFromServer = malloc(sizeof *dataFromServer);
    printf("in main: %p\n", dataFromServer);
    getDataFromServer(&dataFromServer, &size);

    int x;
    for (x=0; x < size; x++)
        printf("%d ", dataFromServer[x]);
    printf("\n\n");
    free(dataFromServer);
    return 0;
}

Выход:

in main: 003F1708
Before realloc: 003F1708
After realloc : 003F3430
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

Из вывода realloc возвращает указатель на новый адрес памяти.

Итак, вопрос в том, должен ли я освободить это местоположение явно - кроме того, чтобы освободить место, созданное оригинальным malloc?

Или он делает то, что желал код, приведенный выше, который является Just expand the memory location reserved previously?

Спасибо.

EDIT: На самом деле каждый ответ, представленный ниже, давал мне ценную информацию. И потому что я должен выбрать только один ответ, чтобы принять. Я выбрал тот, который исправил мой код выше!

Ответы [ 4 ]

5 голосов
/ 20 сентября 2011

После того, как вы позвонили realloc и вернули какой-то указатель, вы должны забыть о предыдущем и просто сохранить «новый» указатель.

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

Но , никогда не перезаписывайте старый указатель с результатом вызова realloc (как вы делаете в своем коде): в действительности, когда realloc не удается, он возвращает NULL и не освобождает старый указатель , поэтому, если вы перезаписываете единственную переменную, в которой вы ее сохранили, вы теряете единственный способ free этой памяти, и таким образом, у вас есть утечка памяти. Итак, «канонический» способ вызова realloc таков:

/* assuming myPtr contains the malloced memory */
void * tempPtr=realloc(myPtr, newSize);
if(tempPtr==NULL)
{
    /* realloc failed, handle the error and, if aborting, free myPtr */
}
else
    myPtr = tempPtr;

/* ... */

/* when you no longer need it free the memory */
free(myPtr);
4 голосов
/ 20 сентября 2011

Здесь есть два случая.

  • Сбой Realloc: вы несете ответственность только за освобождение исходного указателя
  • Успешно Realloc: вы несете ответственность только за освобождение возвращенного указателя

Примечание. Функция realloc не гарантирует расширение области памяти.Фактически его можно использовать для сокращения памяти, выбрав размер 0.

2 голосов
/ 20 сентября 2011

я должен освободить это местоположение явно - кроме того, чтобы освободить местоположение, созданное оригинальным malloc?

Нет.Realloc должен позаботиться об этом.Даже если память перераспределена в новом адресном пространстве, если realloc преуспевает, ранее выделенная память с помощью malloc автоматически освобождается.

1 голос
/ 20 сентября 2011

Realloc может выполнять одно из трех действий:

1) обнаруживает, что ваша предыдущая память может быть расширена без необходимости ее перемешивания.

2) Может удовлетворить ваш запрос, но объект памяти должен быть помещен в другое место.

3) он может потерпеть неудачу.

В вашем случае 1) произошло, так что кажется.РЕДАКТИРОВАТЬ: он вернул другой указатель, поэтому он выбрал 2)

Кстати, в случае 3) он возвращает NULL.Ничего не произошло, и ваш указатель по-прежнему указывает на действительный старый объект.

...