Рассмотрим этот код С++ как пример.
int *A = new int [5];
int *B = new int [5];
int *C = new int [5];
delete []A;
delete []C;
int *D = new int [10];
Очевидно, что любая машина может обрабатывать этот случай без каких-либо проблем с переполнением буфера или утечкой памяти. Однако представьте, что длины умножаются на миллион или даже большее число. Насколько я знаю, адреса (по крайней мере, виртуальные адреса) всех элементов массива являются последовательными. Поэтому всякий раз, когда я создаю массив, я могу быть уверен, что они являются смежными кусками в виртуальной памяти, и я могу выполнить арифметику указателей для доступа к n-му элементу, если у меня есть указатель на первый. Мой вопрос проиллюстрирован на следующем рисунке (регистры, представляющие конец массива, для простоты игнорируются).
После выделения A, B, C в куче мы освобождаем A и C и получаем два свободных фрагмента памяти длиной 5 (помечены зелеными точками). Что произойдет, когда я хочу выделить массив длиной 10? Я думаю, что есть 3 возможных случая.
- Я получаю исключение bad_alloc для не имеющего смежного 10-портового блока памяти.
- Программа автоматически перераспределяет массив B в начало кучи и объединяет остальную неиспользуемую память.
-
Массив D будет разделен на 2 части и сохранен не соприкасаемо, что приведет к не постоянному времени доступа для n-го элемента массива (если имеется гораздо больше двух разделов, он начинает напоминать связанный список, а не массив).
Какой из них является наиболее вероятным ответом или есть другой возможный случай, который я не принимал во внимание?