Правильное использование realloc()
From man realloc: функция realloc () возвращает указатель на вновь выделенную память, которая соответствующим образом выровнена для любой переменной и может быть отличается от ptr или NULL, если запрос не выполняется.
Так вот в этом фрагменте кода:
ptr = (int *) malloc(sizeof(int));
ptr1 = (int *) realloc(ptr, count * sizeof(int));
if(ptr1 == NULL){ //reallocated pointer ptr1
printf("Exiting!!n");
free(ptr);
exit(0);
}else{
free(ptr); //to deallocate the previous memory block pointed by ptr so as not to leave orphaned blocks of memory when ptr=ptr1 executes and ptr moves on to another block
ptr = ptr1; //deallocation using free has been done assuming that ptr and ptr1 do not point to the same address
}
достаточно ли просто предположить, что перераспределенный указатель указывает на другой блок memeory, а не на тот же блок.Потому что, если предположение будет ложным и realloc возвращает адрес исходного блока памяти, на который указывает ptr, а затем free(ptr) выполняется (по причине, приведенной в комментариях), тогда блок памяти будет стерт, и программа сойдет с ума. Должен ли я поставить другое условие, которое будет сравнивать равенство ptr и ptr1 и исключать выполнение свободного(ptr) оператора?
6 ответов
просто не звони free()
на вашем оригинальном ptr в счастливом пути. По существу realloc()
сделал это для вас.
ptr = malloc(sizeof(int));
ptr1 = realloc(ptr, count * sizeof(int));
if (ptr1 == NULL) // reallocated pointer ptr1
{
printf("\nExiting!!");
free(ptr);
exit(0);
}
else
{
ptr = ptr1; // the reallocation succeeded, we can overwrite our original pointer now
}
OP: ... может отличаться от ptr или NULL в случае сбоя запроса.
О: не всегда. NULL
может быть законно возвращен (не сбой), если count
равен 0.
OP: достаточно ли просто предположить, что перераспределенный указатель указывает на другой блок памяти, а не на тот же блок.
A: Нет
OP: должен ли я поставить другое условие, которое будет сравнивать равенство ptr и ptr1 и исключать выполнение свободного (ptr) заявление?
отсутствие.
если realloc()
возвращает NULL
(и count не 0), значение ptr
по-прежнему действует, указывая на данные без изменения размера. free(ptr)
или нет, зависит от ваших целей.
если realloc()
возвращает не NULL
, не free(ptr)
, все готово.
пример: https://codereview.stackexchange.com/questions/36662/critique-of-realloc-wrapper
#include <assert.h>
#include <stdlib.h>
int ReallocAndTest(char **Buf, size_t NewSize) {
assert(Buf);
void *NewBuf = realloc(*Buf, NewSize);
if ((NewBuf == NULL) && (NewSize > 0)) {
return 1; // return failure
}
*Buf = NewBuf;
return 0;
}
применение исправлений правок в комментариях ниже.
чтение этот комп.ленг.С вопрос, выявлены 3 случая:
- " когда он способен, он просто возвращает вам тот же указатель, который вы ему передали."
- " но если он должен перейти в другую часть памяти, чтобы найти достаточно смежного пространства, он вернет другой указатель (и Предыдущее значение указателя станет непригодным для использования)."
- "если
realloc
не может найдите достаточно места вообще, он возвращает нулевой указатель и оставляет предыдущую область выделенной."
это можно перевести непосредственно в код:
int* ptr = (int*)malloc(sizeof(int));
int* tmp = (int*)realloc(ptr, count * sizeof(int));
if(tmp == NULL)
{
// Case 3, clean up then terminate.
free(ptr);
exit(0);
}
else if(tmp == ptr)
{
// Case 1: They point to the same place, so technically we can get away with
// doing nothing.
// Just to be safe, I'll assign NULL to tmp to avoid a dangling pointer.
tmp = NULL;
}
else
{
// Case 2: Now tmp is a different chunk of memory.
ptr = tmp;
tmp = NULL;
}
Итак, если вы думаете об этом, код, который вы разместили, в порядке (почти). Приведенный выше код упрощает:
int* ptr = (int*)malloc(sizeof(int));
int* tmp = (int*)realloc(ptr, count * sizeof(int));
if(tmp == NULL)
{
// Case 3.
free(ptr);
exit(0);
}
else if(ptr != tmp)
{
ptr = tmp;
}
// Eliminate dangling pointer.
tmp = NULL;
отметить лишнее else if(ptr != tmp)
, что исключает Случай 1, где вы не хотели бы вызывать free(ptr)
, потому что ptr
и tmp
обратитесь к тому же месту. Кроме того, просто для безопасности, я делаю назначить NULL
to tmp
чтобы избежать каких-либо проблем с висячим указателем, пока tmp
в области.
realloc
вернет тот же адрес в ptr
Если у него достаточно места для расширения фактического куска памяти, на который указывает ptr
. В противном случае он переместит данные в новый фрагмент и освободит старый фрагмент. Вы не можете положиться на ptr1
отличается от ptr
. Ваша программа ведет себя неопределенно.
если realloc
возвращает другой адрес, он сначала освобождает старый, поэтому вам не нужно делать это самостоятельно.
кстати, никогда не бросайте возвращение malloc/realloc
:). Ваш код должен быть таким:
ptr=malloc(sizeof(int));
ptr=realloc(ptr,count*sizeof(int));
if(ptr==NULL)
{
// error!
printf("\nExiting!!");
// no need to free, the process is exiting :)
exit(0);
}
Если realloc
перемещает ваши данные, он освободит старый указатель для вас за кулисами. У меня нет копии стандарта C11, но это гарантировано в стандарте C99.
вы должны не free
ваш исходный указатель, если realloc
успешно. Являетесь ли вы free
этот указатель, если realloc
не зависит от потребностей конкретного приложения; если вы абсолютно не может продолжать без этой дополнительной памяти это будет фатальная ошибка, и вы освободите любое удерживаемое хранилище и выйдете. Если, OTOH, вы все еще можете продолжить (возможно, выполнить другую операцию и надеяться, что память будет доступна позже), вы, вероятно, захотите сохранить эту память и попытаться другой realloc
позже.
7.22.3.5 функция realloc
справка
1#include <stdlib.h> void *realloc(void *ptr, size_t size);
описание
2 к
realloc
функции освобождает старый объект указываетptr
и возвращает указатель на новый объект, имеющий размер, указанныйsize
. Содержание нового объект должен быть таким же, как у старого объекта до освобождения, до меньшего из новые и старые размеры. Любые байты в новом объекте за пределами размера старого объекта имеют неопределенные значения.3 Если
ptr
является нулевым указателем,realloc
функция ведет себя как для заданный размер. В противном случае, еслиptr
не соответствует указателю, ранее возвращенному памятью функцию управления, или если пространство было освобождено вызовомfree
илиrealloc
функция, поведение не определено. Если памяти для нового объекта не может быть выделенный, старый объект не освобождается и его значение не изменяется.возвращает
4 к
realloc
функция возвращает указатель на новый объект (который может иметь такую же значение как указатель на старый объект), или нулевой указатель, если новый объект не мог быть распределяемый.
Курсив. Примечание п. 4; возвращенный указатель может быть такой же, как и исходный указатель.