본문 바로가기

Computer science/OS

스택 메모리, 힙 메모리

스택 메모리와 힙 메모리

메모리는 왜 필요할까?

프로그램을 구동하려면, 여러 가지 데이터가 필요하다. 

예를 들어 계산기를 만든다고 하자.

10 + 12 = 22를 계산하고, 계산 결과 값에 30을 더하는 프로그램이다. 

const a = 10; 
const b = 12; 
const c = 30;

const d = a + b;
const e = d + c;

 

컴퓨터는 어떻게 10과 12를 알며, 어떻게 10과 12를 더해 22를 만들까?

어딘가에 10과 12가 저장되어 있기 때문이다. 

 

const a = 10;

이 부분에서 컴퓨터는 a라는 변수를 특정 공간에 저장한다. 이 공간이 바로 메모리다. 

즉, 컴퓨터는 a를 저장할 공간을 메모리에 만들고, 그 공간에 10을 부여한다. 

 

이 글을 보고 있는 브라우저도 결국은 계산기와 유사하다. 

a, b, c 같은 변수들을 메모리에 저장하고 저장된 값을 이용해 계산하고, 화면에 보여준다.

그렇기에, 왜 메모리가 필요하냐? 라고 묻는다면 값을 기억하고 다시 사용하기 위해서라고 할 수 있다.

 

왜 스택 메모리와 힙 메모리 두 가지 종류가 있을까?

보통 물건(데이터)을 다른 장소에 보관하는 이유는 관리의 용이성 때문이다. 

책상 위에 있는 물건과 서랍에 넣어 놓은 물건은 접근성에 차이가 있다. 책상 위에 있는 물건은 손을 뻗어 집으면 되지만, 서랍 안에 있는 물건은 서랍을 열고 물건을 찾아야 한다.

 

책상 위에 있는 물건은 물건을 다 사용하고 나서 제자리로 돌려놓는다. 하지만 쓰레기 통에 넣은 물건은 주기적으로 가져다 버린다. 

 

위의 이유와 정확히 같지는 않지만 결국은 비슷한 이유에서 메모리 영역을 나누었다고 생각한다.

 


 

스택 메모리

스택은 컴파일 타임에 크기가 결정되고, 힙은 런타임에 크기가 결정된다.

따라서, 스택 영역이 작으면 컴파일을 반드시 다시 해야 한다.

 

1. 스택 영역에는 함수 호출과 관계되는 지역 변수와 매개변수가 저장된다. (지역 변수 중에도 참조 타입은 스택에 주소만 있고, 값은 힙에 있다. 스택은 힙에 비해 굉장히 작기 때문에 많은 데이터를 스택 영역에 둘 수 없다.)

2. 스택에 저장된 값은 함수의 호출과 함께 할당되며, 함수의 호출이 완료되면 소멸한다.

3. 스택 영역은 LIFO(후입선출)이다.

4. 변수를 명시적으로 할당 해제할 필요가 없다. 메모리 공간은 CPU에 의해 효율적으로 관리되고 메모리는 단편화되지 않는다.

 

스택 오버플로우

스택 오버플로우를 직역하면 스택이 가득 차 넘쳤다는 말이다. 

스택은 아래에서부터 위로 쌓아가는 구조이다. 통에 감자칩을 넣는다는 비유를 많이 한다. 가장 마지막에 넣은 감자칩을 가장 먼저 꺼낼 수밖에 없다. 

아래서 위로 쌓을 때, 통이 가득 찼는데도 계속 넣으면 흘러넘치게 된다. 이것이 스택 오버플로우다.

스택에 넣는 것은 감자칩이 아니라 스택 프레임이라고 부른다.

스택 오버플로우는 통에 너무 많은 스택 프레임을 집어넣었을 때 발생한다. 

 

이제 코드와 함께 스택에 데이터가 쌓이는 것을 보자.

1. function adder(a, b) {
2. 	return a + b;
3. }
4. 
5. const result = adder(5, 2);

2번에서 스택에 저장된 값은 함수의 호출과 함께 할당되며, 함수의 호출이 완료되면 소멸한다고 했다. 

5번째 줄에서 'adder'함수를 호출하며 스택에 프레임이 쌓인다. 

 

1번에서 스택 영역에는 함수 호출과 관계되는 지역 변수와 매개변수가 저장된다고 했다.

stack 영역에 매개 변수인 a = 5와 b = 2, 함수를 실행하고 돌아올 위치 5번째 줄이 저장된다. 

 

2번째 줄에서 a+b를 리턴해주며 함수 호출이 완료된다. 따라서 스택에 있는 (a = 5, b =2, 돌아올 위치 = 5번째 줄) 프레임이 소멸되며, 돌아올 위치 5번째로 돌아온다. 

 

1. function adder(a, b) {
2. 	return adder(a, b);
3. }
4. 
5. const result = adder(5, 2);

다음과 같은 상황에서 스택 오버플로우가 발생한다.

5번째 줄에서 adder를 실행하여 스택에 프레임이 쌓인다. (a = 5, b = 2, 돌아올 위치 = 5번째 줄)

2번에서 다시 adder를 실행하며 스택에 프레임이 쌓인다. (a = 5, b = 2, 돌아올 위치 = 2번째 줄)

2번에서 다시 adder를 실행하며 스택에 프레임이 쌓인다. (a = 5, b = 2, 돌아올 위치 = 2번째 줄)

2번에서 다시 adder를 실행하며 스택에 프레임이 쌓인다. (a = 5, b = 2, 돌아올 위치 = 2번째 줄)

...

스택에서 프레임이 빠지진 않고 쌓이기만 한다. 그리고 이 스택 안에는 데이터가 들어 있다(a = 5, b = 2, 돌아올 위치 = 2번째 줄). 즉, 메모리를 차지한다.

이 과정이 반복되다 보면 스택에 할당된 메모리가 가득 차고, 스택이 오버플로우 하는 것이다.

 


힙 메모리

힙 영역은 사용자가 직접 관리할 수 있는 메모리 영역이다. 사용자에 의해 메모리 공간이 동적으로 할당되고 해제된다.

1. 상대적으로 느린 접근 속도. 

2. 객체를 선언하면 항상 힙 메모리 영역에 생성된다. 이러한 객체에 대한 참조 정보는 스택 메모리에 저장된다. 

3. 할당 해제를 잘하지 못하면 메모리 릭이 발생한다.

4. 전역 변수를 저장한다.

 

사용자에 의해 메모리 공간이 동적으로 할당된다는 것은 unmanged 언어인 C가 그렇고,

C#, Java, Javascript는 managed 언어이기 때문에 Garbage Collector에 의해 메모리가 할당 해제된다.

 

메모리 릭이 발생하면 Out of Memory 오류와 함께 프로세스가 종료된다. 

JS에서는 클로저에 의해 메모리 릭이 발생할 수 있다.

 

 


 

* JS에서의 Stack

스택이 컴파일 타임에 생성되면 런타임인 JS에서는 스택이 언제 생성될까?

Node.js에서 사용되는 V8 엔진은 JIT 컴파일을 채택했다. JIT는 인터프리터와 정적 컴파일러의 중간 단계라고 볼 수 있다. JIT 컴파일러는 실행 단계에서 컴파일되는 것이기 때문에 미리 스택 크기를 결정지을 수 없다. V8엔진에서는 통상 1만개의 스택이 쌓이면 스택 오버 플로우가 일어난다고 한다. , 1만 개만개 정도의 스택 프레임을 감당할 크기의 스택이 생긴다. 스택 영역에 사용되는 메모리의 경우 데이터는 힙에 생기고 스택에는 포인터만 있기 때문에 무한 재귀 함수가 일어나지 않는 이상 오버플로우는 거의 일어나지 않는다고 한다. 추가로, JS는 비동기 함수를 많이 사용하는데 비동기의 경우 스택을 빠르게 비울 수 있다.

             브라우저는 16000프레임의 제한된 스택을 가지고 있기 때문에 해당 범위를 넘어서게 되면 에러를 출력하면서 실행 중이던 것을 모두 종료한다.

 

 

 

blog.naver.com/jaeeun_98/222211408294

 

[JavaScript] 자바스크립트 동작 원리 이해하기, 호출 스택(Call Stack)과 힙(Heap)_모든 자바스크립트 개

1. Javascript Engine​자바스크립트의 동작 원리를 이해하기 위해선, 우선적으로 자바스크립트 엔진에 ...

blog.naver.com

levelup.gitconnected.com/understanding-call-stack-and-heap-memory-in-js-e34bf8d3c3a4

 

Understanding Call Stack and Heap Memory in JS

Hi guys, I promised in my previous post: Hoisting in JavaScript that I would talk about the reason why we can’t change values into a const…

levelup.gitconnected.com

hashnode.com/post/does-javascript-use-stack-or-heap-for-memory-allocation-or-both-cj5jl90xl01nh1twuv8ug0bjk

 

Does JavaScript use stack or heap for memory allocation or both? - Hashnode

Answer (1 of 3): First of all, JavaScript is based on the ECMA-262 standard, which does not define memory layout, so whatever it uses depends on how the inte

hashnode.com

steemit.com/kr/@cicada0014/2wvmzm-javascript

 

Javascript 메모리 에 대하여! — Steemit

자바스크립트를 사용하면서 메모리단에서의 동작 및 주의점에 대해 공부해 보았습니다. 일반적인 정적 언어와 달리 자바스크립트에서의 메모리 동작은 조금 다른 부분이 있어 궁금증을 가지고

steemit.com

guslabview.tistory.com/186

 

[.NET] C# 스택(Stack)과 힙(Heap) 메모리의 차이

오늘은 스택과 힙메모리의 차이에 대해서 알아보도록 하겠습니다. C#에서도 당연히 스택기반의 메모리와 힙 기반의 메모리를 제공합니다. C#에서 이 메모리들의 구조를 확인하기 위해서는 먼저

guslabview.tistory.com

 

'Computer science > OS' 카테고리의 다른 글

가상 메모리는 왜 필요할까?  (0) 2021.04.02