Каждый виртуальный адрес, к которому вы пытаетесь получить доступ, сопоставляется операционной системой с физической памятью. Физическая память выделяется в страницах (например, размером 4 КБ). Если вам удастся выделить байт со смещением 1000000 * n и сделать это для n от 1 до 1000000 (я думаю, что может сделать это с помощью mmap), то ОС придется подкрепить это миллионом страницы физической памяти, что-то вроде 4G. Эта физическая память не будет доступна ни для чего другого. Если бы вы распределили байты непрерывно, вам понадобится всего около 1M физической памяти (256 страниц) для вашего миллиона байтов.
Вы можете попасть в аналогичную плохую ситуацию, если выделите 4G по законным причинам, а затем освободите его части, сохранив часть каждой выделенной страницы. ОС не сможет фактически использовать освобожденную память для чего-либо еще, потому что нет физических страниц, которые полностью свободны. Так что это проблема фрагментации.
Теоретически можно представить, что виртуальные адреса 1000000 и 2000000 будут отображаться на одной и той же странице физической памяти, избегая фрагментации. Но на практике и по уважительным причинам отображение виртуальной памяти выполняется постранично. Подробнее об этом можно прочитать здесь: http://en.wikipedia.org/wiki/Page_table.