История изменений
Исправление
Moisha_Liberman,
(текущая версия)
:
Стек — это не системный ресурс, а локальный ресурс процесса.
Если смотреть со стороны процесса, то да, владельцем стека как ресурса, является процесс. Он может его увеличивать. Нет, уменьшать процесс ни стек, ни кучу не может. Если выделение памяти произошло, то либо куча, либо стек выросли, но даже если Вы освободите память в случае с кучей через free(), или она сама освободится как в случае со стеком, уменьшения отведённого программе адресного пространства не произойдёт. Так сделано во предположении что если программе раз понадобилась область памяти (не важно – в куче или в стеке), то чтоб системе потом не париться, в случае, если память освободилась, но потом понадобилась опять, у программы уже будет выделен кусок нужного размера.
Если смотреть со стороны системы, то нет. Именно на уровне системы (ulimit) задаются дефолтные и общесистемные настройки, которые потом по мере необходимости корректируются процессом, если у него есть на это права. Посмотреть и откорректировать свои дефолтные настройки Вы можете в файле /etc/security/limits.conf
. Т.е., именно система определяет как будет жить ваш процесс на старте. Но именно процесс потом корректирует своё поведение, если может.
Программа всегда может сама выделить стек через malloc
Нет. Система через malloc() новый размер стека установить не может. Он устанавливается либо напрямую, через setrlimit(), либо косвенно, в процессе работы программы – через alloca(), либо при использовании динамических массивов. В случае через setrlimit() я сразу говорю какой стек мне по идее нужен, а система уже пытается выделить мне нужное пространство (и ещё о своих задачах не забывает, т.е., на деле будет стек для приложения, нужный приложению для работы + стек приложения нужный мне лично). В случае с alloca() и динамическими массивами система по запросу будет выделять нужные участки стека, точно так же увеличивая размер стека приложения, но происходит это в менее явном для меня виде. Т.е., в первом случае я хотя бы прикинуть могу какой размер стека у меня в приложении будет, во втором-третьем случаях меня это вообще не парит.
или mmap и
Нет. Области памяти, закреплённые за виртуальным адресным пространством процесса, выделенные через mmap() никакого отношения не имеют ни к стеку, ни к куче. Это отдельные регионы памяти, которые ни в стек, ни в кучу не входят. Это data segment приложения. С ним можно делать что угодно.
Если в куче работает malloc(), точнее, внутри там работают sbrk()/brk() (хотя, если уж быть совсем точным, то всё сводится к одному сисколлу brk()), то работа с mmap() строится на том, что mmap() создаёт некий разделяемый сегмент, который доступен процессу, который его создал. Более того, я сразу уточню что если нужны небольшие объёмы памяти, то они будут выделяться через malloc()/brk(), а вот значительные объёмы будут выделяться через mmap() скорее всего. Так сделано чтобы не отдавать процессу запрашиваемые им пару гигабайт «навечно», пока он не закончит свою работу (выше я написал что ни куча ни стек не уменьшаются, а data segment может и расти и убывать).
установить SP на него и система ничего с этим сделать не сможет.
Стек адресуется как адрес_стека+смещение через регистры SS:ESP для х86_64. Подходя формально, Вам конечно запретить сделать что-то типа mov esp, new_value
нельзя. Но вот компилятор скорее всего может неоценить такого подхода и, в случае включённых опций компиляции типа -fstack-protector-strong{all||explicit} не одобрить Ваших действий.
Система тут и делать ничего не должна, если по большому счёту. Должны же «злобные хаккИры» как-то свои атаки типа stack smashing проводить… =)))
Исходная версия
Moisha_Liberman,
:
Не совсем так.
Стек — это не системный ресурс, а локальный ресурс процесса.
Если смотреть со стороны процесса, то да, владельцем стека как ресурса, является процесс. Он может его увеличивать. Нет, уменьшать процесс ни стек, ни кучу не может. Если выделение памяти произошло, то либо куча, либо стек выросли, но даже если Вы освободите память в случае с кучей через free(), или она сама освободится как в случае со стеком, уменьшения отведённого программе адресного пространства не произойдёт. Так сделано во предположении что если программе раз понадобилась область памяти (не важно – в куче или в стеке), то чтоб системе потом не париться, в случае, если память освободилась, но потом понадобилась опять, у программы уже будет выделен кусок нужного размера.
Если смотреть со стороны системы, то нет. Именно на уровне системы (ulimit) задаются дефолтные и общесистемные настройки, которые потом по мере необходимости корректируются процессом, если у него есть на это права. Посмотреть и откорректировать свои дефолтные настройки Вы можете в файле /etc/security/limits.conf
. Т.е., именно система определяет как будет жить ваш процесс.
Программа всегда может сама выделить стек через malloc
Нет. Система через malloc() новый размер стека установить не может. Он устанавливается либо напрямую, через setrlimit(), либо косвенно, в процессе работы программы – через alloca(), либо при использовании динамических массивов. В случае через setrlimit() я сразу говорю какой стек мне по идее нужен, а система уже пытается выделить мне нужное пространство (и ещё о своих задачах не забывает, т.е., на деле будет стек для приложения, нужный приложению для работы + стек приложения нужный мне лично). В случае с alloca() и динамическими массивами система по запросу будет выделять нужные участки стека, точно так же увеличивая размер стека приложения, но происходит это в менее явном для меня виде. Т.е., в первом случае я хотя бы прикинуть могу какой размер стека у меня в приложении будет, во втором-третьем случаях меня это вообще не парит.
или mmap и
Нет. Области памяти, закреплённые за виртуальным адресным пространством процесса, выделенные через mmap() никакого отношения не имеют ни к стеку, ни к куче. Это отдельные регионы памяти, которые ни в стек, ни в кучу не входят. Это data segment приложения. С ним можно делать что угодно.
Если в куче работает malloc(), точнее, внутри там работают sbrk()/brk() (хотя, если уж быть совсем точным, то всё сводится к одному сисколлу brk()), то работа с mmap() строится на том, что mmap() создаёт некий разделяемый сегмент, который доступен процессу, который его создал. Более того, я сразу уточню что если нужны небольшие объёмы памяти, то они будут выделяться через malloc()/brk(), а вот значительные объёмы будут выделяться через mmap() скорее всего. Так сделано чтобы не отдавать процессу запрашиваемые им пру гигабайт «навечно», пока он не закончит свою работу (выше я написал что ни куча ни стек не уменьшаются, а data segment может и расти и убывать).
установить SP на него и система ничего с этим сделать не сможет.
Стек адресуется как адрес_стека+смещение через регистры SS:ESP для х86_64. Подходя формально, Вам конечно запретить сделать что-то типа mov esp, new_value
нельзя. Но вот компилятор скорее всего может неоценить такого подхода и, в случае включённых опций компиляции типа -fstack-protector-strong{all||explicit} не одобрить Ваших действий.
Система тут и делать ничего не должна, если по большому счёту. Должны же «злобные хаккИры» как-то свои атаки типа stack smashing проводить… =)))