Изложу свои догадки, пусть кто-нибудь меня поправит. Как я понимаю, аппаратным стеком может служить абсолютно любая часть оперативной памяти. Физически он никак не выделен, существует столько, сколько выполняется программа. ОС выделяет по одному стеку на каждую выполняемую программу. Все верно?
Почти.
(Все, что я дальше буду говорить, касается ОС Windows и соответственно архитектуры x86. О других вариантах пусть говорят другие).
По всей видимости, говоря "аппаратный стек", топикстартер имеет в виду ту структуру данных, для работы с которой в архитектуре x86 существуют специальные инструкции.
Если так, то да, для стека может быть выделена любая область памяти - по усмотрению операционной системы. ОС выделяет, строго говоря, по
два стека каждому
потоку - стек режима пользователя и стек режима ядра. Программа может быть многопоточной, у каждого потока свой стек. Все дальнейшее - только про стек режима пользователя.
Но я не понимаю, почему ограничение в 1 Мб не срабатывает.
Как было сказано выше, 1MB - это всего лишь значение по умолчанию. Оно прописывается в заголовке исполняемого файла и может быть изменено параметром /STACK компоновщика. Подробности -
тут.
Когда программа исчерпывает выделенную область и хочет получить еще, возникает страничный отказ. Диспетчер памяти его обрабатывает и выделяет еще памяти - если есть. Если нету, программа получает исключение с кодом STATUS_STACK_OVERFLOW.
В вашем случае 8 MB это совсем немного, поэтому память успешно выделяется.