realloc
| Определено в заголовочном файле <stdlib.h>
|
||
void *realloc( void *ptr, size_t new_size ); |
||
Перевыделяет заданную область память. Если ptr не NULL, он обязан быть ранее выделен malloc(), calloc() или realloc() и не освобождён вызовами free или realloc. Иначе результаты не определены.
Перевыделение выполняется одним из следующих способов:
ptr, если возможно. Содержимое области остаётся неизменным вплоть до меньшего из нового и старого размеров. Если область расширяется, содержимое новой части массива не определено. new_size байтов, копированием области памяти размером, меньшим из нового и старого, и освобождением старого блока.Если памяти не достаточно, старый блок памяти не освобождается и возвращается нулевой указатель.
Если ptr равен NULL поведение такое же как при вызове malloc(new_size).
Иначе,
|
если |
(до C23) |
|
если |
(начиная с C23) |
|
Предшествующий вызов free или |
(начиная с C11) |
Параметры
| ptr | — | указатель на область памяти для перевыделения |
| new_size | — | новый размер массива в байтах |
Возвращаемое значение
При успехе возвращает указатель на начало новой выделенной памяти. Во избежание утечек памяти возвращённый указатель должен быть освобождён с помощью free() или realloc(). Оригинальный указатель ptr аннулируется и любой доступ к нему является неопределённым поведением (даже если перевыделение произошло на месте).
При неудаче возвращает нулевой указатель. Оригинальный указатель ptr остаётся действительным и, возможно, должен быть освобождён с помощью free() или realloc().
Замачения
Изначально (в C89) была добавлена поддержка нулевого размера для размещения кода, как
OBJ *p = calloc(0, sizeof(OBJ)); // заполнитель "нулевой длины"
...
while(1) {
p = realloc(p, c * sizeof(OBJ)); // перевыделения, пока не подойдёт размер
... // код, который может изменять c или выходить из цикла
}
Пример
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void print_storage_info(const int* next, const int* prev, int ints) {
if (next) {
printf("%s location: %p. Size: %d ints (%ld bytes).\n",
(next != prev ? "New" : "Old"), (void*)next, ints, ints * sizeof(int));
} else {
printf("Allocation failed.\n");
}
}
int main(void)
{
const int pattern[] = {1, 2, 3, 4, 5, 6, 7, 8};
const int pattern_size = sizeof pattern / sizeof(int);
int *next = NULL, *prev = NULL;
if ((next = (int*)malloc(pattern_size * sizeof *next))) { // выделяет массив
memcpy(next, pattern, sizeof pattern); // заполняет массив
print_storage_info(next, prev, pattern_size);
} else {
return EXIT_FAILURE;
}
// Перевыделяет в цикле с использованием следующих значений в качестве новых размеров памяти.
const int realloc_size[] = {10, 12, 512, 32768, 65536, 32768};
for (int i = 0; i != sizeof realloc_size / sizeof(int); ++i) {
if ((next = (int*)realloc(prev = next, realloc_size[i] * sizeof(int)))) {
print_storage_info(next, prev, realloc_size[i]);
assert(!memcmp(next, pattern, sizeof pattern)); // pattern не меняется?
} else { // если realloc потерпела неудачу, оригинальный указатель должен быть освобождён
free(prev);
return EXIT_FAILURE;
}
}
free(next); // наконец, освобождает память
return EXIT_SUCCESS;
}
Возможный вывод:
New location: 0x144c010. Size: 8 ints (32 bytes).
Old location: 0x144c010. Size: 10 ints (40 bytes).
New location: 0x144c450. Size: 12 ints (48 bytes).
Old location: 0x144c450. Size: 512 ints (2048 bytes).
Old location: 0x144c450. Size: 32768 ints (131072 bytes).
New location: 0x7f490c5bd010. Size: 65536 ints (262144 bytes).
Old location: 0x7f490c5bd010. Size: 32768 ints (131072 bytes).
Ссылки
- Стандарт C17 (ISO/IEC 9899:2018):
- 7.22.3.5 Функция realloc (стр. 254)
- Стандарт C11 (ISO/IEC 9899:2011):
- 7.22.3.5 Функция realloc (стр. 349)
- Стандарт C99 (ISO/IEC 9899:1999):
- 7.20.3.4 Функция realloc (стр. 314)
- Стандарт C89/C90 (ISO/IEC 9899:1990):
- 4.10.3.4 Функция realloc
См. также
Документация C++ по realloc
|