Тут надо понимать, что с точки зрения времени выполнения есть понятие "объект в куче". Указатели указывают на такие "объекты в куче".

Объекты в куче делятся на два вида: динамические массивы и записи.
Сборщик мусора для массивов смотрит, есть в элементах массива указатели. Если да, то обходит каждый элемент.
В случае для записи сборщик обращается к её описателю типа, в котором есть список всех позиций, на которых в экземпляре записи лежат указатели. И идёт по этим указателям.

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