Что происходит с памятью при уменьшении массива с помощью realloc? - PullRequest
0 голосов
/ 25 декабря 2018

Мне было интересно, что происходит с памятью, когда вы перераспределяете -1 ваш массив.Исходя из всего, что я прочитал о realloc, я предполагаю, что указатель по-прежнему указывает на то же место в памяти (функция не нуждается в поиске другого блока памяти, поскольку этот доступен и достаточно), скажите мне, если я ошибаюсь.У меня такой вопрос: удаленный фрагмент массива удален (как при использовании free ()), или значения остаются без изменений, а часть памяти используется совместно для будущих операций malloc, calloc и т. Д .?

EDIT: У меня еще один вопрос.Эта функция работает правильно?Следует удалить элемент массива, предварительно переписав его следующим элементом массива.Делая это по всему массиву, последний элемент такой же, как предыдущий, а последний удаляется.PicCounter - это количество картинок, уже загруженных в программу.Проверьте это:

int DeletePicture(struct Picture **tab, int *PicCounter)
{
int PicToDelete;
printf("Enter the number of pic to delete ");
scanf("%d", &PicToDelete);
for (int i = PicToDelete - 1; i < (*PicCounter) - 2; i++)
{
    (*tab)[i] = (*tab)[i + 1];
}

struct Picture *temp;
temp = realloc(*tab, ((*PicCounter)-1) * sizeof(*temp));
if (temp != NULL)
{
    *tab = temp;
 //That doesn't delete the element, because in main I can still print it
 //like e.g. tab[lastelement]. 
    (*PicCounter)--;
    printf("Picture has been deleted\n");
    return 0;
}
else
{
    printf("Memory reallocation error\n");
    return 1;
}
}

1 Ответ

0 голосов
/ 25 декабря 2018

Относительно void *realloc(void *ptr, size_t size), стандарт C говорит в C 2018 7.22.3.5 параграфы 2 и 3:

Функция realloc освобождает старый объект, на который указывает ptr, и возвращаетуказатель на новый объект, размер которого указан size.Содержимое нового объекта должно быть таким же, как и у старого объекта до освобождения, до меньшего из нового и старого размеров.Любые байты в новом объекте, превышающие размер старого объекта, имеют неопределенные значения.

Если ptr является нулевым указателем, функция realloc ведет себя как функция malloc для указанного размера.В противном случае, если ptr не совпадает с указателем, ранее возвращенным функцией управления памятью, или если пространство было освобождено при вызове функции free или realloc, поведение не определено.Если size не равен нулю и память для нового объекта не выделена, старый объект не освобождается.Если size равен нулю и память для нового объекта не выделена, то определяется реализацией, освобожден ли старый объект.Если старый объект не освобожден, его значение должно быть неизменным.

Что это означает, когда вы просите уменьшить размер ранее выделенного объекта:

  • Возвращенный указатель может совпадать или не совпадать с исходным указателем.(См. Обсуждение ниже.)

  • Стандарт C допускает повторное использование части памяти, которая высвобождается для других выделений.Независимо от того, используется ли оно повторно или нет, зависит от реализации языка Си.

  • Независимо от того, перезаписаны ли значения в освобожденной части памяти или нет, стандарт C не определен.Конечно, пользователь realloc не может полагаться на какое-либо поведение в отношении этой памяти.

Обсуждение

Когда выделение памяти сокращается, это, безусловно, кажется «легким» дляпроцедуры выделения памяти просто возвращают тот же указатель, помня, что освобожденная память свободна.Однако системы выделения памяти довольно сложны, поэтому могут быть задействованы и другие факторы.Например, гипотетически:

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

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

...