Stack och heap i C/C++
Taget från en annan tråd då jag inte orkar skriva.
Ok, jag skrev om hur det fungerar på svenska. Men ett extremt hett tips: Lär dig engelska! Det är extremt viktigt, inte bara för programmering. Det är typ det viktigaste du kan göra, tätt efter att äta mat och andas.
En stack (stack = stapel på svenska) är en datastruktur där man bara kan lägga
till nya element överst, och ta bort element överst, d.v.s. i omvänd ordning som
man la till dem (som på en stapel tallrikar). Stacken, i bestämd form, är en
sådan datastruktur som programmet använder när det körs för att lagra data som
det (programmet) behöver.
På stacken läggs lokala variabler och argument. Säg att du har följande kod.
(Koden är ganska meningslös, men jag hade dålig fantasi.)
int add(int x, int y) {
int result = x + y;
return result;
}
void print_times(int x, int times) {
for (int i = 0; i < times; i++) {
Console.WriteLine(x);
}
}
void add_and_print_3_times(int a, int b) {
int sum = add(a, b);
print_times(sum, 3);
}
static int Main(string[] args) {
add_and_print_3_times(3, 17);
return 0;
}
Du är i början av main. Då ser stacken ut som följer:
-----------------------------
args: 0x239797
-----------------------------
D.v.s. det finns bara en sak på stacken: variablen args som är en referens
till en string[].
När vi anropar add_and_print_3_times(3, 17) så kommer det minne som den
metoden behöver att allokeras på stacken, så i början av
add_and_print_3_times(3, 17) så ser stacken ut:
-----------------------------
a: 3
b: 17
sum: (inget)
-----------------------------
args: 0x239797
-----------------------------
Strecken här (---) använder jag för att man ska se var metoders "stack frames"
börjar och slutar. Det första add_and_print_3_times gör är att anropa
add(3, 17). Då ser stacken ut:
-----------------------------
x: 3
y: 17
result: (inget)
-----------------------------
a: 3
b: 17
sum: (inget)
-----------------------------
args: 0x239797
-----------------------------
Nästa sak programmet gör är att köra raden `int result = x + y;`. Programmet
lagrar då 20 i resultat-platsen på stacken:
-----------------------------
x: 3
y: 17
result: 20
-----------------------------
a: 3
b: 17
sum: (inget)
-----------------------------
args: 0x239797
-----------------------------
När add-metoden returnerar så tas det minnet bort från stacken (det ligger
överst, eller hur?). Säg att tilldelningen i raden `int sum = add(a, b);`
också sker, då kommer stacken att se ut:
-----------------------------
a: 3
b: 17
sum: 20
-----------------------------
args: 0x239797
-----------------------------
Nu ska print_times(20, 3) anropas. print_times har också lokala variabler och
argument, så stacken kommer att se ut:
-----------------------------
x: 20
times: 3
i: (inget)
-----------------------------
a: 3
b: 17
sum: 20
-----------------------------
args: 0x239797
-----------------------------
Medan loopen i print_times körs så kommer givetvis `i` att uppdateras. När
print_times är klar så tas det minnet bort igen, och vi får kvar:
-----------------------------
a: 3
b: 17
sum: 20
-----------------------------
args: 0x239797
-----------------------------
Nu är add_and_print_3_times också klar, och vi får kvar:
-----------------------------
args: 0x239797
-----------------------------
Sammanfattningvis: På stacken läggs lokala variabler och argument (och kanske
lite mer grejer, men det är inte jätteviktigt). Det är viktigt att inse att
när man anropar en metod så kommer alltid metodens stack frame (dess variabler
och argument) att hamna överst på stacken. Och när man är klar med en metod så
kommer alltid dess stack frame att ligga överst, så vi kan ta bort den utan
problem.
Så hur används heapen?
Jo, args i Main är ju en string[]. string[]:er läggs på heapen, och det som
sparas på stacken, (här: `args: 0x239797`) är en adress till den. Så på
heapen, på plats 0x239797 så ligger en string[]. Så är det med alla lokala
variabler som är av en referenstyp, d.v.s. inte en primitiv (int, double,
bool, o.s.v.). Om en stackframe som refererar till ett objekt tas bort (för
att vi är klara med den metoden) så förlorar vi referensen till objektet om vi
inte hade sparat undan den nånstans. Om vi nu inte har kvar några referenser
till objektet så kommer objektet så småningom att städas undan av garbage
collectorn.
Notera att 0x239797 är ett vanligt nummer, men man brukar skriva adresser i hexadecimalform (0x betyder hexadecimalform).
@Petrikus: Tack för svaret!
Jag tror detta visar när jag har problem:
#include <iostream>
int main()
{
int stack [1000000]; // 4 Mbytes big
std::cout<<" stack-test ";
return 0;
}
Detta slutar fungera om jag ökar stacken med en nolla till.
Trist då att kompilatorn inte ger någon varning....
Men om man kör malloc så kan man allokera betydligt mer.
Det ser ut att vara vanligaste sättet för stora arrayer med double eller float.
Men man måste tydligen frigöra minne på slutet.
Hur stor stack du kan använda beror på vilken miljö som koder körs under.
I många fall är maximal stack storlek begränsad endast av tillgängligt minne, men i andra fall kan den vara ganska så liten. För kod inuti Linux-kerneln så är stacken t.ex. begränsad till två minnessidor - 8KB/16/KB för 32-/64-bitars arkitekturer.
Allokeringar på heapen har inga särskilda begränsningar annat än de begränsningar som finns på programmet som helhet.
Sen så är det ju stor skillnad på hur minnet hanteras när det gäller stack kontra heap. Stackalloceringar är lokala för ett givet funktionsanrop och försvinner därmed när funktionen är klar.
Allokeringar på heapen måste man ofta frigöra själv när man är klar med dem, såvida man inte använder ett programmeringsspråk med automatisk garbage collection.
.
Det ser ut att vara stor skillnad på Linux för X86_64 och Raspberry Pi4(ARM64).
I bägge fall verkar "default stack" vara 8192 bytes. Men X86_64 klarar sig betydligt längre innan man får fel.
Kan det bero på att swap är betydligt större?(Lika stor som RAM)
Med Raspberry Pi får man köra ulimit -s unlimited så fungerar det mesta.
- Idag Apple kan släppa ny Ipad Pro med M4-krets 21
- Igår Intel skyller Raptor Lake-krascher på moderkortstillverkare 31
- Igår TSMC utvecklar enorma kretsar med effekt mätt i kilowatt 11
- Igår Så mycket långsammare blir Intels värstingkretsar med ”Intel Baseline” i BIOS 55
- 26 / 4 Corsair Platform 6: För dig som inte nöjer dig med Ikea-skrivbord 11
- 27 / 4 Stöd för komprimering i fler format på gång till Windows 19
- 27 / 4 Krönika: "Early access" är utstuderad girighet 50
- 27 / 4 Microsoft släpper källkoden till MS‑DOS 4.00 22
- 26 / 4 Ny caps lock-symbol i Windows förbryllar HP-användare 21
- 26 / 4 Därför blockerar Windows 11 24H2 Start‑menyhack 43
- Domkraft puck6
- Därför är Googles sökresultat sämre6
- Krönika: "Early access" är utstuderad girighet51
- Apple kan släppa ny Ipad Pro med M4-krets22
- Uppgradering CPU/Mobo/Minnen/lagring.2
- [LEK] Gissa spelet15521
- Vilken film såg du senast?13387
- Rabbel.se - Ett dagligt ordspel715
- Hur funkar e-sim?8
- PTM7950 Thermal Pad40
- Säljes MSI Katana 15 - i7 | 16GB | 1TB | RTX 4070
- Säljes Dell UltraSharp U2723QE 27" 4K UHD IPS
- Säljes Nybyggd Vattenkyld Dator
- Säljes 4070 TI i5 13400f Dator
- Säljes ASUS ROG Strix 3080 10GB White
- Säljes CoD MW3 ps5 inkl lockpick, Noctua NH-U12S AM4, DAC och HDD
- Säljes Elgato Wave 3 mikrofon
- Säljes TC-Helicon GoXLR Mini
- Säljes Komplett dator, 2700x, GTX 1070
- Säljes Vårstädning - i5-6600, GA-H170N-WIFI, 2x8GB DDR4, GTX 760, Noctua NH-U12S, FD Tesla 650W
- Därför är Googles sökresultat sämre5
- Apple kan släppa ny Ipad Pro med M4-krets22
- Google nöjda med annonsexperiment: Youtube kan få pausreklam44
- Intel skyller Raptor Lake-krascher på moderkortstillverkare31
- TSMC utvecklar enorma kretsar med effekt mätt i kilowatt11
- Så mycket långsammare blir Intels värstingkretsar med ”Intel Baseline” i BIOS55
- Stöd för komprimering i fler format på gång till Windows19
- Krönika: "Early access" är utstuderad girighet51
- Övergivet skadeprogram infekterar miljontals maskiner20
- Helgsnack: Är all reklam av ondo?85
Externa nyheter
Spelnyheter från FZ
- Ny Stalker 2-trailer bjuder på svindlande utsikt idag
- 1 miljon sålda Manor Lords på bara en dag idag
- Escape From Tarkov pudlar angående sitt exklusiva PvE-läge idag
- Dragon’s Dogma 2 har sålt så bra att Capcom betalar ut mer pengar till aktieägarna igår
- Silent Hill 2 – Snart avslöjas släppdatum och till vilka plattformar det släpps igår