Кіріспе
Компьютерлік жадты бөлу түрі
Есептеу архитектураларындағы стектер – деректер соңғы кірген, бірінші шықты (LIFO) қағидасы бойынша қосылатын немесе алынып тасталатын жад аймақтары. Көптеген қазіргі заманғы компьютерлік жүйелерде әрбір жіпшеде оның стегі деп аталатын резервтелген жад аймағы болады. Функция орындалғанда, ол өзінің жергілікті күй деректерінің бір бөлігін стек жоғарғы жағына қосуы мүмкін; функция аяқталғанда, ол осы деректерді стекен алып тастауға жауапты. Міндетті түрде, қайтару операторларының дұрыс орынға оралуын қамтамасыз ету үшін, шақырушы берген қайтару мекенжайының орналасуын сақтау үшін жіпшенің стегі қолданылады. Көбінесе стек қазіргі белсенді функцияларға қатысты тұрақты ұзындығы бар айнымалыларды сақтау үшін пайдаланылады. Бағдарламашылар өзгермелі ұзындығы бар жергілікті деректерді сақтау үшін стекті нақты түрде пайдалануды таңдауы мүмкін. Егер жад аймағы жіпшенің стегінде орналасса, онда бұл жад стекте бөлінген деп есептеледі, яғни стекке негізделген жадты бөлу (SBMA). Бұл жинаққа негізделген жадты бөлу (HBMA) әдісімен салыстырылады. SBMA көбінесе функция шақыру стегімен тығыз байланысты болады.
Артықшылықтары мен кемшіліктері
Деректер соңғы қосылып, бірінші алынатындықтан, стекке негізделген жадты бөлу өте қарапайым және әдетте үйіндіге негізделген жадты бөлуден (динамикалық жадты бөлу деп те аталады) жылдам. Мысалы, C тілінде. Тағы бір ерекшелік – стектегі жад функция аяқталғанда автоматты түрде және өте тиімді түрде босатылады, егер деректер енді қажет болмаса, бұл бағдарламашы үшін ыңғайлы болуы мүмкін. (Осыған ұқсасы longjmp функциясы шақырудан бұрынғы нүктеге оралғанда да орын алады.) Егер деректерді қандайда бір түрінде сақтау қажет болса, функция аяқталмас бұрын оларды стектегі үйіндіге көшіру керек. Сондықтан, стекке негізделген бөлу уақытша деректерге немесе ағымдағы функция аяқталғаннан кейін қажет болмайтын деректерге қолайлы. Тік тізбектегі стек мөлшері кейбір кіші процессорларда бірнеше байтқа дейін кіші болуы мүмкін. Стекте қол жетімді жадтан артық жадты бөлу стек ағынына байланысты қатеге әкелуі мүмкін. Сондықтан, alloca функциясын пайдаланатын функциялардың инлайн болуына көбінесе рұқсат берілмейді: егер мұндай функция циклге инлайн болса, шақырушы күтпеген стек пайдаланудың өсуінен зардап шегеді, бұл ағынның болу ықтималдығын арттырады. Стекке негізделген бөлу шағын өнімділік мәселелерін де тудыруы мүмкін: ол өзгермелі өлшемді стек кадрларына әкеледі, сондықтан стек және кадр көрсеткіштерін басқару қажет (белгілі өлшемді стек кадрларында стек көрсеткіші артық болады, өйткені кадр көрсеткішін әр кадрдың өлшеміне көбейту жеткілікті). Бұл әдетте alloca және free функцияларын шақырудан гөрі арзан. Атап айтқанда, егер ағымдағы функцияда alloca шақырулары мен өзгермелі ұзындығы бар жергілікті деректерді қамтитын блоктар болса, alloca ағымдағы функция аяқталғанға дейін стек кадрын ұлғайтуға тырысады, ал компилятор өзгермелі ұзындығы бар жергілікті айнымалыларды стек кадрындағы бір орынға орналастыруы керек арасында қайшылық туындайды. Бұл қайшылық әдетте alloca әр шақырылғанда жеке үйінді сақтау тізбегін құру арқылы шешіледі. Тізбек әр бөлу орын алған стек тереңдігін тіркейді, ал кез келген функциядағы alloca-ға келесі шақырулар осы тізбекті ағымдағы стек тереңдігіне дейін қысқартады, содан кейін (бірақ бірден емес) осы тізбектегі кез келген сақтауды босатады. Alloca функциясын нөлдік аргументпен шақыру жадты бөлусіз босатуды іске қосу үшін де пайдаланылуы мүмкін. Alloca және жергілікті сақтау арасындағы осы қайшылықтың салдарынан alloca-ны пайдалану malloc-ты пайдаланудан тиімдірек болмауы мүмкін.
Another feature is that memory on the stack is automatically, and very efficiently, reclaimed when the function exits, which can be convenient for the programmer if the data is no longer required. (The same applies to longjmp if it moved to a point before the call to happened.) If, however, the data needs to be kept in some form, then it must be copied from the stack to the heap before the function exits. Therefore, stack based allocation is suitable for temporary data or data which is no longer required after the current function exits. A thread's assigned stack size can be as small as only a few bytes on some small CPUs. Allocating more memory on the stack than is available can result in a crash due to stack overflow. This is also why functions that use are usually prevented from being inlined: should such a function be inlined into a loop, the caller would suffer from an unanticipated growth in stack usage, making an overflow much more likely. Stack based allocation can also cause minor performance problems: it leads to variable size stack frames, so that both stack and frame pointers need to be managed (with fixed size stack frames, the stack pointer is redundant due to multiplying the stack frame pointer by the size of each frame). This is usually much less costly than calling and anyway. In particular, if the current function contains both calls to alloca and blocks containing variable length local data then a conflict occurs between alloca's attempts to increase the current stack frame until the current function exits versus the compiler's need to place local variables of variable length in the same location in the stack frame. This conflict is typically resolved by creating a separate chain of heap storage for each call to alloca. The chain records the stack depth at which each allocation occurs, subsequent calls to alloca in any function trim this chain down to the current stack depth to eventually (but not immediately) free any storage on this chain. A call to alloca with an argument of zero can also be used to trigger the freeing of memory without allocating any more such memory. As a consequence of this conflict between alloca and local variable storage, using alloca might be no more efficient than using malloc.
Жүйелік интерфейс
Көптеген Unix сияқты жүйелер де, Microsoft Windows та, үйіндіге негізделген malloc сияқты, стек жадын динамикалық түрде бөлуге арналған функцияны іске асырады. Компилятор әдетте оны қатарлы сілтемені басқаратын, өзгермелі ұзындығы бар массивтерді өңдеуге ұқсас, тікелей кодқа аударады. Жадты ашық түрде босатудың қажеті болмаса да, стек асып кетуі салдарынан белгісіз мінез-құлыққа ұшырау қаупі бар. Бұл функция Unix жүйелерінде 32/V (1978) нұсқасынан бастап қолданылып келген, бірақ ол Standard C немесе кез келген POSIX стандартының бөлігі емес. Microsoft Windows жүйесінде , егер бөлінетін көлем тым үлкен болса, үйіндіде жад бөліп беретін және стек асып кету қателерін хабарлайтын, қауіпсіз нұсқасы бар. Ол gnulib кітапханасын пайдалануды талап етеді, ол эквивалентті интерфейсті ұсынады, бірақ стек асып кетуі кезінде SEH ерекшелігін тудырудың орнына, аса үлкен өлшем анықталғанда функциясын шақырады. Осыған ұқсас мүмкіндікті қолмен есептеу және өлшемді тексеру арқылы эмуляциялауға болады, мысалы, glibc кітапханасында қолданылатынындай. Кейбір процессорлар отбасылары, мысалы x86, ағымдағы орындалып жатқан жіптің стегін басқаруға арналған арнайы нұсқауларға ие. Басқа процессорлар, соның ішінде RISC V, PowerPC және MIPS, тікелей стек қолдауын қамтамасыз етпейді, керісінше, конвенцияға сүйенеді және стек басқаруды операциялық жүйенің қолданбалық бинарлық интерфейсіне (ABI) жүктейді.