스택(Stack)


스택에는 함수호출, Function Call에서 메모리 할당이 일어난다.

함수 호출에 쓰이는 지역변수, 매개변수가 저장되고 함수호출에 대한 활성 레코드들이 들어간다.

또한 return address가 있어서 다시 프로시저로 돌아갈 수 있게 한다.

 

즉, 함수가 종료될 경우 다시 반환하는 형식이다.

(함수가 종료되지 않고 계속 쌓이는 경우 스택오버플로우가 발생할 수 있다)

또한 크기가 OS나 컴파일러에 의해 결정된다.

공간은 CPU에 의해 효율적으로 관리되고, 메모리는 단편화되지 않는다. (스택 특성)

 

스택은 접근이 매우 빠르고, 변수를 명시적으로 할당 해제할 필요가 없다.

컴파일러에 의해 메모리 해제 할당이 된다.

 

스택

  • 스택은 제한적으로 접근할 수 있는 나열 구조를 띈 자료구조이다.
  • 접근 방법은 언제나 목록의 한 쪽 끝에서만 이루어지는 선형 구조(LIFO - Last In First Out)로 되어있다.
    • 최근에 추가한 항목이 가장 먼저 저게된다.
  • 자료를 넣는 행위는 Push, 빼는 것을 Pop이라 한다.
  • 이와는 반대로 처음 추가한 항목이 가장 먼저 제거되는 Queue 자료구조가 있다(FIFO - First In First Out)

 

 

 

힙(Heap)


힙에는 동적으로 메모리를 할당할 때 사용한다. 즉 개발자가 할당시키는 것이다.

 

완전이진트리

  • 힙은 최댓값 및 최솟값을 찾아내는 연산을 빠르게 하기 위해 고안된 완전이진트리(complete binary tree)를 기본으로 한 자료구조다.
    • 완전이진트리란 2개씩 노드가 분리되는 트리 자료구조에 왼쪽부터 차례대로 노드를 추가하여 구현할 수 있는 형태를 뜻한다.
  • 부모의 키값이 자식보다 항상 큰 힙을 최대 힙, 항상 작은 힙을 최소 힙이라 한다.

 

 

 

메모리 구조


메모리 구조

 

데이터 영역
  • 전역 변수, static variable들이 저장된다.
  • 숫자나 문자열 값인 리터럴도 저장된다.
    • 리터럴이란 소스코드의 고정된 값을 말한다. 즉, int i = 1; 에서 1을 말한다.
  • 생존주기, Life Cycle은 프로그램의 시작부터 끝까지 가지고 있다.

 

코드 영역
  • 프로그램 코드가 저장되고 절대 변경되지 않는 구역이다.
  • CPU는 코드 영역에 저장된 명령어를 하나씩 가져와서 처리한다.

 

스택 영역
  • 컴퓨터에서 포인터라고 하는 자료의 위치 표시자와 넣고 빼는 명령어를 사용해서 스택을 이용한다.
  • 메모리의 스택 영역은 함수의 호출과 관계되는 지역변수(local variable)와 매개변수(parameter)가 저장되는 영역이다.
  • 스택 영역은 함수의 호출과 함께 할당되며, 함수의 호출이 완료되면 소멸한다.
  • 주로 함수를 호출할 때 인수의 전달 등에 이용된다.
  • 스택 영역은 메모리의 높은 주소에서 낮은 주소의 방향으로 할당된다.
  • 매우 빠르게 액세스 된다.
  • 변수를 명시적으로 할당 해체 할 필요가 없다.
    • scope가 해체(pop)될 때 일괄적으로 해체 된다.
  • 공간은 CPU에 의해 효율적으로 관리 된다.
  • OS에 따라 스택 크기에 제한이 있을 수 있다.
  • 변수의 크기를 조정할 수 없다.
자바에서의 스택 영역

1. 원시타입의 데이터가 값과 함께 할당된다.
2. Heap 영역에 생성된 Object 타입의 데이터의 참조값이 할당된다
3. 각 쓰레드(Thread)는 자신만의 stack을 가진다.

 

힙 영역
  • 사용자가 직접 관리할 수 있는 메모리 영역이다.
  • 사용자에 의해 메모리 공간이 동적으로 할당되고 해제된다.
  • 메모리의 낮은 주소에서 높은 주소의 방향으로 할당된다.
  • 메모리 크기에 제한이 없다.
  • (상대적으로) 액세스가 느리다.
  • 효율적으로 공간 사용을 보장하지 못하면 메모리 블록이 할당 된 후 시간이 지남에 따라 메모리가 조각화되어 해제 될 수 있다.
  • 메모리를 관리해야 한다(변수의 할당과 해제에 책임이 있다).
자바에서의 힙 영역

1. 모든 Object 타입(Integer, String, ArrayList, …)은 heap 영역에 생성된다.
2. 몇개의 스레드가 존재하든 상관없이 단 하나의 heap 영역만 존재한다.
3. heap 영역에 있는 오브젝트들을 가리키는 레퍼런스 변수가 stack에 올라가게 된다.

 

 


 

그렇다면 왜 스택과 힙을 나눠놓았는가?


스택은 매우 빠르게 접근과 할당이 가능하며 메모리에 낭비되는 공간이 없이 사용가능하다.

스택의 의미대로 그냥 차례대로 쌓기 때문이다. (연속적 메모리 영역)

하지만 용량이 무척 적다는 단점이 있다.

 

힙은 사용자가 따로 할당, 관리를 해서 사용해야 하는 공간으로 스택보단 느리게 할당된다.

용량은 크지만 단편화의 위험성을 가지고 있다.

하지만 크기를 먼저 설정해주는 스택영역보다 유연함을 가지고 있는 것이 장점이다.

또한 제대로 반환하지 않으면 Memory Leak이 일어나서 메모리에 손해를 볼 수 있다.

 

 

 

모든 영역을 빠르고 단편화도 없는 Stack으로 구현하면 안되는가?


안된다.

Stack의 특성상 데이터에 접근할 수 있는 부분은 top밖에 없다.

Stack에 활성레코드가 저장될 수 있는 이유이자 Stack 자료구조를 적용할 수 있는 이유이며

함수가 실행중일 때만 접근 가능한 공간이다

때문에 중간에 접근하려고 해도 불가능한 경우가 많다.

그래서 Heap에 할당을 하게되면 pointer로 해당 데이터에 접근이 가능하게 된다.

 

 

즉, 스택과 힙을 나눠놓은 목적은 


프로그램 상에서 얼마나 메모리가 필요할 지 모르는 상태이고

미리 모두 할당해놓은 것은 쓰이지 않을 메모리까지 할당되어 있는 비효율적인 상태에 놓일 수 있으므로

스택, 힙으로 나누어 할당을 하는 것이라고 할 수 있다.

 

 

 

 

 

참고 사이트 : 
https://luv-n-interest.tistory.com/1046
https://sklubmk.github.io/2021/11/01/0a6d4d441931/

 

'WebBase' 카테고리의 다른 글

[WebBase] CORS Error  (0) 2023.03.07
[WebBase] 부동소수점 오차 문제와 해결법  (0) 2023.02.08
[WebBase] Spring에서 Ajax로 JSON데이터 받기  (0) 2022.07.20
[WebBase] jQuery.ajax  (0) 2022.06.23
[WebBase] Ajax  (0) 2022.06.23

+ Recent posts