12.2 — The stack and the heap - Learn C++
文章推薦指數: 80 %
With stack allocated memory, the compiler can keep track of the relationship between a variable's name and it's memory address, and translate ...
Thememorythataprogramusesistypicallydividedintoafewdifferentareas,calledsegments:Thecodesegment(alsocalledatextsegment),wherethecompiledprogramsitsinmemory.Thecodesegmentistypicallyread-only.Thebsssegment(alsocalledtheuninitializeddatasegment),wherezero-initializedglobalandstaticvariablesarestored.Thedatasegment(alsocalledtheinitializeddatasegment),whereinitializedglobalandstaticvariablesarestored.Theheap,wheredynamicallyallocatedvariablesareallocatedfrom.Thecallstack,wherefunctionparameters,localvariables,andotherfunction-relatedinformationarestored.Forthislesson,we’llfocusprimarilyontheheapandthestack,asthatiswheremostoftheinterestingstufftakesplace.TheheapsegmentTheheapsegment(alsoknownasthe“freestore”)keepstrackofmemoryusedfordynamicmemoryallocation.Wetalkedabouttheheapabitalreadyinlesson11.11--Dynamicmemoryallocationwithnewanddelete,sothiswillbearecap.InC++,whenyouusethenewoperatortoallocatememory,thismemoryisallocatedintheapplication’sheapsegment.int*ptr=newint;//ptrisassigned4bytesintheheap
int*array=newint[10];//arrayisassigned40bytesintheheapTheaddressofthismemoryispassedbackbyoperatornew,andcanthenbestoredinapointer.Youdonothavetoworryaboutthemechanicsbehindtheprocessofhowfreememoryislocatedandallocatedtotheuser.However,itisworthknowingthatsequentialmemoryrequestsmaynotresultinsequentialmemoryaddressesbeingallocated!int*ptr1=newint;
int*ptr2=newint;
//ptr1andptr2maynothavesequentialaddressesWhenadynamicallyallocatedvariableisdeleted,thememoryis“returned”totheheapandcanthenbereassignedasfutureallocationrequestsarereceived.Rememberthatdeletingapointerdoesnotdeletethevariable,itjustreturnsthememoryattheassociatedaddressbacktotheoperatingsystem.Theheaphasadvantagesanddisadvantages:Allocatingmemoryontheheapiscomparativelyslow.Allocatedmemorystaysallocateduntilitisspecificallydeallocated(bewarememoryleaks)ortheapplicationends(atwhichpointtheOSshouldcleanitup).Dynamicallyallocatedmemorymustbeaccessedthroughapointer.Dereferencingapointerisslowerthanaccessingavariabledirectly.Becausetheheapisabigpoolofmemory,largearrays,structures,orclassescanbeallocatedhere.ThecallstackThecallstack(usuallyreferredtoas“thestack”)hasamuchmoreinterestingroletoplay.Thecallstackkeepstrackofalltheactivefunctions(thosethathavebeencalledbuthavenotyetterminated)fromthestartoftheprogramtothecurrentpointofexecution,andhandlesallocationofallfunctionparametersandlocalvariables.Thecallstackisimplementedasastackdatastructure.Sobeforewecantalkabouthowthecallstackworks,weneedtounderstandwhatastackdatastructureis.ThestackdatastructureAdatastructureisaprogrammingmechanismfororganizingdatasothatitcanbeusedefficiently.You’vealreadyseenseveraltypesofdatastructures,suchasarraysandstructs.Bothofthesedatastructuresprovidemechanismsforstoringdataandaccessingthatdatainanefficientway.Therearemanyadditionaldatastructuresthatarecommonlyusedinprogramming,quiteafewofwhichareimplementedinthestandardlibrary,andastackisoneofthose.Considerastackofplatesinacafeteria.Becauseeachplateisheavyandtheyarestacked,youcanreallyonlydooneofthreethings:LookatthesurfaceofthetopplateTakethetopplateoffthestack(exposingtheoneunderneath,ifitexists)Putanewplateontopofthestack(hidingtheoneunderneath,ifitexists)Incomputerprogramming,astackisacontainerdatastructurethatholdsmultiplevariables(muchlikeanarray).However,whereasanarrayletsyouaccessandmodifyelementsinanyorderyouwish(calledrandomaccess),astackismorelimited.Theoperationsthatcanbeperformedonastackcorrespondtothethreethingsmentionedabove:Lookatthetopitemonthestack(usuallydoneviaafunctioncalledtop(),butsometimescalledpeek())Takethetopitemoffofthestack(doneviaafunctioncalledpop())Putanewitemontopofthestack(doneviaafunctioncalledpush())Astackisalast-in,first-out(LIFO)structure.Thelastitempushedontothestackwillbethefirstitempoppedoff.Ifyouputanewplateontopofthestack,thefirstplateremovedfromthestackwillbetheplateyoujustpushedonlast.Laston,firstoff.Asitemsarepushedontoastack,thestackgrowslarger--asitemsarepoppedoff,thestackgrowssmaller.Forexample,here’sashortsequenceshowinghowpushingandpoppingonastackworks:Stack:empty
Push1
Stack:1
Push2
Stack:12
Push3
Stack:123
Pop
Stack:12
Pop
Stack:1
Theplateanalogyisaprettygoodanalogyastohowthecallstackworks,butwecanmakeabetteranalogy.Considerabunchofmailboxes,allstackedontopofeachother.Eachmailboxcanonlyholdoneitem,andallmailboxesstartoutempty.Furthermore,eachmailboxisnailedtothemailboxbelowit,sothenumberofmailboxescannotbechanged.Ifwecan’tchangethenumberofmailboxes,howdowegetastack-likebehavior?First,weuseamarker(likeapost-itnote)tokeeptrackofwherethebottom-mostemptymailboxis.Inthebeginning,thiswillbethelowestmailbox(onthebottomofthestack).Whenwepushanitemontoourmailboxstack,weputitinthemailboxthatismarked(whichisthefirstemptymailbox),andmovethemarkeruponemailbox.Whenwepopanitemoffthestack,wemovethemarkerdownonemailbox(soit’spointedatthetopnon-emptymailbox)andremovetheitemfromthatmailbox.Anythingbelowthemarkerisconsidered“onthestack”.Anythingatthemarkerorabovethemarkerisnotonthestack.ThecallstacksegmentThecallstacksegmentholdsthememoryusedforthecallstack.Whentheapplicationstarts,themain()functionispushedonthecallstackbytheoperatingsystem.Thentheprogrambeginsexecuting.Whenafunctioncallisencountered,thefunctionispushedontothecallstack.Whenthecurrentfunctionends,thatfunctionispoppedoffthecallstack.Thus,bylookingatthefunctionspushedonthecallstack,wecanseeallofthefunctionsthatwerecalledtogettothecurrentpointofexecution.Ourmailboxanalogyaboveisfairlyanalogoustohowthecallstackworks.Thestackitselfisafixed-sizechunkofmemoryaddresses.Themailboxesarememoryaddresses,andthe“items”we’repushingandpoppingonthestackarecalledstackframes.Astackframekeepstrackofallofthedataassociatedwithonefunctioncall.We’lltalkmoreaboutstackframesinabit.The“marker”isaregister(asmallpieceofmemoryintheCPU)knownasthestackpointer(sometimesabbreviated“SP”).Thestackpointerkeepstrackofwherethetopofthecallstackcurrentlyis.Wecanmakeonefurtheroptimization:Whenwepopanitemoffthecallstack,weonlyhavetomovethestackpointerdown--wedon’thavetocleanuporzerothememoryusedbythepoppedstackframe(theequivalentofemptyingthemailbox).Thismemoryisnolongerconsideredtobe“onthestack”(thestackpointerwillbeatorbelowthisaddress),soitwon’tbeaccessed.Ifwelaterpushanewstackframetothissamememory,itwilloverwritetheoldvaluewenevercleanedup.ThecallstackinactionLet’sexamineinmoredetailhowthecallstackworks.Hereisthesequenceofstepsthattakesplacewhenafunctioniscalled:Theprogramencountersafunctioncall.Astackframeisconstructedandpushedonthestack.Thestackframeconsistsof:Theaddressoftheinstructionbeyondthefunctioncall(calledthereturnaddress).ThisishowtheCPUrememberswheretoreturntoafterthecalledfunctionexits.Allfunctionarguments.MemoryforanylocalvariablesSavedcopiesofanyregistersmodifiedbythefunctionthatneedtoberestoredwhenthefunctionreturnsTheCPUjumpstothefunction’sstartpoint.Theinstructionsinsideofthefunctionbeginexecuting.Whenthefunctionterminates,thefollowingstepshappen:RegistersarerestoredfromthecallstackThestackframeispoppedoffthestack.Thisfreesthememoryforalllocalvariablesandarguments.Thereturnvalueishandled.TheCPUresumesexecutionatthereturnaddress.Returnvaluescanbehandledinanumberofdifferentways,dependingonthecomputer’sarchitecture.Somearchitecturesincludethereturnvalueaspartofthestackframe.OthersuseCPUregisters.Typically,itisnotimportanttoknowallthedetailsabouthowthecallstackworks.However,understandingthatfunctionsareeffectivelypushedonthestackwhentheyarecalledandpoppedoffwhentheyreturngivesyouthefundamentalsneededtounderstandrecursion,aswellassomeotherconceptsthatareusefulwhendebugging.Atechnicalnote:onsomearchitectures,thecallstackgrowsawayfrommemoryaddress0.Onothers,itgrowstowardsmemoryaddress0.Asaconsequence,newlypushedstackframesmayhaveahigheroralowermemoryaddressthanthepreviousones.AquickanddirtycallstackexampleConsiderthefollowingsimpleapplication:intfoo(intx)
{
//b
returnx;
}//fooispoppedoffthecallstackhere
intmain()
{
//a
foo(5);//fooispushedonthecallstackhere
//c
return0;
}Thecallstacklookslikethefollowingatthelabeledpoints:a:main()
b:foo()(includingparameterx)
main()
c:main()
StackoverflowThestackhasalimitedsize,andconsequentlycanonlyholdalimitedamountofinformation.OnWindows,thedefaultstacksizeis1MB.Onsomeunixmachines,itcanbeaslargeas8MB.Iftheprogramtriestoputtoomuchinformationonthestack,stackoverflowwillresult.Stackoverflowhappenswhenallthememoryinthestackhasbeenallocated--inthatcase,furtherallocationsbeginoverflowingintoothersectionsofmemory.Stackoverflowisgenerallytheresultofallocatingtoomanyvariablesonthestack,and/ormakingtoomanynestedfunctioncalls(wherefunctionAcallsfunctionBcallsfunctionCcallsfunctionDetc…)Onmodernoperatingsystems,overflowingthestackwillgenerallycauseyourOStoissueanaccessviolationandterminatetheprogram.Hereisanexampleprogramthatwilllikelycauseastackoverflow.Youcanrunitonyoursystemandwatchitcrash:#include
延伸文章資訊
- 1C++ Dynamic Memory - Tutorialspoint
You can allocate memory at run time within the heap for the variable of a given type using a spec...
- 212.2 — The stack and the heap - Learn C++
With stack allocated memory, the compiler can keep track of the relationship between a variable's...
- 3How much stack usage is too much?
- 4在C++ 中利用堆疊與堆記憶體分配| D棧- Delft Stack
在C++ 中利用堆疊與堆記憶體分配. C++ · C++ Memory. 創建時間: June-28 ...
- 512.2 — The stack and the heap - Learn C++