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 Quiz: Har du koll på det senaste inom processorkylare? 64
- Idag Cooler Master Ncore 100 Max – lättbyggt minstingchassi 12
- Igår Nytt vetenskapligt genombrott kan lösa OLED-inbränning 45
- Igår Microsoft vill göra handhållen Xbox 41
- 26 / 3 Microsoft patenterar teknik för bättre ray tracing-prestanda 27
- Idag Svenska Embracer säljer Gearbox för 4,9 miljarder kronor 12
- Idag Var femte användare har lämnat X sedan Musk tog över 110
- Igår Veckans fråga: Hur gammalt är ditt Steam-konto? 162
- Igår Bluffkampanj sprider sig genom Googles AI-sökfunktion 11
- 26 / 3 82 studenter avstängda för AI-fusk – Uppsala strängast 55
- Playstation 5 Skärm1
- En gamingdator för någon som gärna vill spela spel ett par år.20
- Quiz: Har du koll på det senaste inom processorkylare?64
- Var femte användare har lämnat X sedan Musk tog över110
- Kontakt fiberkabel5
- Inet frågar SweClockers – vilken roll spelar designen när du väljer teknikprylar?58
- [LEK] Gissa spelet15332
- Herman Miller X Logitech G Embody Gaming Chair, recension?110
- Vilka obskyra elektronikmärken på Amazon.se är bra och pålitliga?58
- GRUB meny linux till windows1
- Köpes Desktop/"server"/Workstation, 128gb RAM (t.ex. LGA 2011-system) eller delar till sådant system
- Säljes Playstation 5 - Digital Edition
- Säljes Acer Nitro N50-600 (9400F, 1660 Ti, 32 GB RAM & 500 GB SSD)
- Säljes Utförsäljning: 3 stycken helt nya roomba robotdammsugare säljes till bra pris.
- Säljes Kingston 32GB (2x16GB) DDR5 6000MHz CL36 FURY Beast
- Säljes Gigabyte B650I Aorus Ultra AM5 - garanti
- Säljes apple macbook pro 16 m1 max 32gb ram 1tb ssd
- Säljes Apple iPad Pro 11'' 5G (gen 4)
- Säljes Xbox Series S
- Säljes B550-f/5900x/32gb
- Ny RAM-sparande funktion upptäckt i Microsoft Edge7
- Quiz: Har du koll på det senaste inom processorkylare?64
- Svenska Embracer säljer Gearbox för 4,9 miljarder kronor12
- Cooler Master Ncore 100 Max – lättbyggt minstingchassi12
- Var femte användare har lämnat X sedan Musk tog över110
- Så byter du till gamla Notepad i Windows 1132
- Microsoft Copilot kan snart köras direkt på datorn13
- Stort steg för Windows på ARM: Google släpper optimerat Chrome26
- Nytt vetenskapligt genombrott kan lösa OLED-inbränning45
- Xbox-chef är öppen för fler spelbutiker på konsol23