Перезаписывает ли realloc старое содержимое?


Когда мы перераспределяем память через realloc(), переписывается ли предыдущее содержимое? Я пытаюсь создать программу, которая перераспределяет память каждый раз, когда мы вводим в нее данные.

Пожалуйста, расскажите мне о выделении памяти через realloc, это зависит от компилятора, например?

4 30

4 ответа:

Не беспокойтесь о старом содержании.

Правильный способ использования realloc состоит в том, чтобы использовать определенный указатель для перераспределения, проверить этот указатель и, если все сработало нормально, изменить старый указатель

int *oldpointer = malloc(100);

/* ... */

int *newpointer = realloc(oldpointer, 1000);
if (newpointer == NULL) {
    /* problems!!!!                                 */
    /* tell the user to stop playing DOOM and retry */
    /* or free(oldpointer) and abort, or whatever   */
} else {
    /* everything ok                                                                 */
    /* `newpointer` now points to a new memory block with the contents of oldpointer */
    /* `oldpointer` points to an invalid address                                     */
    oldpointer = newpointer;
    /* oldpointer points to the correct address                                */
    /* the contents at oldpointer have been copied while realloc did its thing */
    /* if the new size is smaller than the old size, some data was lost        */
}

/* ... */

/* don't forget to `free(oldpointer);` at some time */

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

Вы должны программировать так, как если бы старый указатель был перезаписан, да. Старая память больше не выделяется, поэтому может быть повторно выделена другой частью вашей программы (или системным потоком, например) и записана в любое время после вызова realloc.

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

Если вам нужна копия, сделайте новый malloc и используйте memcpy.

С точки зрения реализации, когда вы вызываете realloc для увеличения размера, может произойти одно из следующих событий:

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

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

Трудно сказать, о чем вы спрашиваете, но если вы спрашиваете, можете ли вы прочитать "старое содержимое" по старому адресу, переданному в realloc, ответ будет нет. В некоторых случаях вы можете найти там часть или все старое содержимое, но если realloc не вернет тот же указатель, который вы ему передали, любое использование старого указателя будет неопределенным поведением.

Если вы просто спрашиваете, будет ли сохранено старое содержимое на новом адресе, возвращенном realloc, ответ-да (до минимум старого размера и нового размера).