포스트

[번역] Stack과 Heap 메모리 할당의 비교

본 글은 Stack vs Heap Memory Allocation(Rajesh P.S저)를 한국어로 번역하여 옮긴 글입니다.

Stack vs Heap 메모리 할당

프로그래밍 언어에서 메모리 관리는 스택(Stack)과 힙(Heap)이라는 두 가지 주요한 메모리 영역으로 구분되어 있습니다. 스택은 정적 메모리 할당에 사용되는 반면에, 힙은 동적 메모리 할당으로 사용됩니다. 이 두 메모리 영역은 컴퓨터의 램(RAM, Random Access Memory) 내에 있으며, 데이터를 관리하는 아주 중요한 기능을 수행합니다.

스택(Stack)

스택에 할당된 변수는 메모리에 직접 저장됩니다. 이 메모리에 접근하는 건 매우 빠르며, 변수의 할당은 프로그램이 캄파일 될 때 처리됩니다. 함수나 메서드가 다른 함수를 호출하고, 해당 함수가 또 다른 함수를 호출할 때, 이러한 모든 함수의 실행은 가장 최근에 호출된 함수가 반환될 때까지 중단됩니다. 스택은 언제나 후입선출(LIFO, Last In First Out) 동작을 보장하며, 가장 최근에 추가된 블록(Block)1은 곧 해제될 블록이라는 것을 의미합니다. 이로 인해 스택에서 블록을 해제하는 건 단순히 하나의 포인터를 조정하면 되므로 매우 간단합니다.

힙(Heap)

힙에 할당된 변수는 런타임 중 메모리에 할당됩니다. 이로 인해 할당된 메모리에 접근하는 일은 (스택에 비해) 상대적으로 느립니다. 그러나 힙은 고정된 크기를 가지지 않으며, 가상 메모리(Virtual Memory)에 따라 크기가 달라집니다. 스택과는 달리 힙은 할당된 블록은 상호 의존성이 없으며, 언제든지 임의로 접근하는 게 가능합니다. 힙은 블록의 유연한 할당과 해제를 허용하며, 개발자들이 필요로 할 때마다 블록을 할당하고 더 이상 필요하지 않을 때는 해제하도록 할 수 있습니다. 그러나 이러한 특징은 메모리 할당과 해제에 더 큰 복잡성을 요구하며, 가용 영역을 주의 깊게 추적해야 합니다.

1

스택과 힙의 선택

스택은 일정 크기의 데이터가 할당되리라는 사실을 알고 있어 컴파일 타임에 결정할 수 있는 상황에 적합합니다. 힙은 데이터의 크기를 컴파일 타임에 알 수 없거나, 큰 크기의 데이터를 할당할 때 적합합니다. 스택은 할당할 데이터가 고정되어 있고, 접근을 빠르게 하고자 할 때 이점이 있습니다. 스택은 후입선출 동작을 보장하므로 데이터 접근을 빠르게 할 수 있습니다. 이런 이유로 스택은 메모리 관리를 매우 빠르고 간단하게 할 수 있으며, 함수와 관련된 매개변수 혹은 지역변수를 관리하는 데 적합합니다. 반면에 힙은 런타임에 동적으로 데이터를 할당하고 해제하는 게 가능합니다. 데이터의 크기가 정해지지 않았거나, 인스턴스, 문자열 혹은 배열과 같인 큰 데이터를 처리해야 할 때 유용합니다. 스택과 힙 중 어느 것을 선택해야 할 지는 프로그램의 특정 요구 사항과 처리해야 하는 데이터의 성격에 따라 달라집니다. 각 메모리 영역의 특징과 트레이드-오프(Trade-Off)를 이해하는 건 효율적인 메모리 관리를 위한 결정에 큰 도움을 줍니다.

멀티 쓰레드 환경에서 메모리 할당

다중 쓰레드(Multi-Thread) 환경에서는 각 쓰레드가 독립된 스택을 가지고 있어 개별적으로 메모리를 관리합니다. 하지만 응용 프로그램 내 쓰레드는 서로 힙을 공유하며, 응용 프로그램 전반에 걸쳐 메모리 할당을 담당합니다. 스택은 예외 처리2와 쓰레드 실행3이 서로 복잡하게 연관되어 있다는 점도 주의깊게 짚어보아야 합니다. 반면에 힙은 개별 쓰레드를 넘어서 응용 프로그램 전체에서 메모리 할당을 요구합니다. 스택과 힙을 구별하는 건 다중 쓰레드 환경에서 효과적인 예외 처리와 쓰레드 실행을 위해 매우 중요합니다.

스택과 힙의 주요한 차이

스택과 힙의 주요 차이점을 정리하면 아래 표와 같습니다.

스택(Stack)

구분내용
메모리 할당스택은 컴파일 타임에 (크기가 고정된) 정적인 메모리를 할당합니다.
메모리 관리스택의 메모리는 시스템에 의해 자동으로 관리되며, 후입선출(LIFO) 동작을 보장하므로 할당과 해제가 매우 빠릅니다.
메모리 사용스택은 함수와 관련된 매개변수와 지역벼수 그리고 반환되면 되돌아갈 주소 정보를 저장합니다.
크기 제한스택의 크기는 시스템에 의해 결정되며, 일반적으로 힙에 비해 작습니다.
쓰레드 안전멀티 쓰레드 환경에서 각 쓰레드는 독립된 스택을 가집니다.

힙(Heap)

구분내용
메모리 할당힙은 런타임에 (크기가 변하는) 동적인 메모리를 할당합니다.
메모리 관리힙의 메모리는 프로그래머가 필요에 따라 직접 할당 및 해제를 함으로써 수동으로 관리해야 합니다.
메모리 사용힙은 인스턴스, 배열과 문자열과 같은 데이터를 저장합니다.
크기 제한힙은 고정된 크기에 의해 제한되지 않으며, 가상 메모리가 허용하는 한 무한대로 커질 수 있습니다.
쓰레드 안전멀티 쓰레드 환경에서 힙은 모든 쓰레드가 공유합니다.

결론

스택과 힙은 메모리 할당과 관리 방식, 속도, 크기 제한과 사용 방법에서 차이가 있습니다. 스택은 스레드에 독립적이고 작은 크기의 데이터를 할당하는 데 효율적인 반면에, 힙은 쓰레드에 공유되며 큰 크기의 데이터를 동적으로 유연하게 할당할 수 있습니다.


  1. 스택 프레임을 의미합니다. 함수가 호출될 때마다 스택 프레임이 생성되고, 해당 함수의 매개변수와 지역변수가 스택 프레임에 할당됩니다. 함수가 반환되면 스택 프레임도 사라집니다. 

  2. 예외 처리는 응용 프로그램의 실핼 중 발생하는 예기치 않은 예외(Arithmetic Overflow, Divide By Zero 등)에 대처하는 것으로, 응용 프로그램의 비정상적인 종료를 막고, 원할한 실행 흐름을 보장하는 것을 목적으로 합니다. 예외가 발생하면 현재 실행 중인 함수들의 스택 프레임을 거슬러 올라가며 예외를 처리할 수 있는 적절한 예외 처리 코드를 찾습니다. 이를 ‘스택 언와인딩(Stack Unwinding)’이라 합니다. 스택이 빌 때까지 적절한 예외 처리 코드를 찾지 못하면, 응용 프로그램은 그대로 종료됩니다. 

  3. 쓰레드는 함수를 호출하면 스택에 함수와 관련된 매개 변수와 지역 변수, 그리고 함수가 반환되면 되돌아갈 주소 정보를 계속해서 쌓아가며 저장합니다. 쓰레드는 이렇게 쌓은 스택을 이용해 쓰레드의 실행 흐름을 제어하고 관리합니다. 

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.