Search

스택, 힙 메모리

Class
메모리
Type
메모리 구조
Created
2023/12/27 05:15
updated
2024/02/07 01:13
날짜

스택, 힙 메모리를 알아야되는 이유

스택(Stack)과 힙(Heap) 메모리에 대해 자세히 알아야 하는 이유는 여러 가지가 있습니다.

1. 메모리 관리의 이해

효율적인 메모리 사용 : 스택과 힙의 차이를 이해함으로써 메모리를 효율적으로 사용할 수 있습니다. 이는 프로그램의 성능과 안정성에 직접적인 영향을 미칩니다.
메모리 할당 및 해제 : 스택은 자동으로 메모리를 할당 및 해제하지만, 힙은 수동으로 관리해야 합니다. 이를 잘 이해하면 메모리 누수와 같은 문제를 예방할 수 있습니다.
힙을 수동으로 관리한다는 것은, GC가 자동으로 수거하는 것뿐만 아니라, GC가 수거할 수 있도록 설정하는 것을 의미합니다.

2. 성능 최적화

데이터 접근 속도 : 스택은 힙에 비해 데이터 접근 속도가 빠릅니다. 성능이 중요한 애플리케이션에서는 이러한 특성을 고려하여 메모리를 할당해야 합니다.
가비지 컬렉션(GC) 최소화 : C#과 같은 언어에서는 힙에 할당된 객체를 가비지 컬렉터가 정리합니다. 가비지 컬렉션은 성능 저하를 일으킬 수 있으므로, 이를 효율적으로 관리하는 것이 중요합니다.
사실, 이 부분이 가장 중요하다고 생각합니다. 가비지 컬렉션을 일으키지 않기 위해, 오브젝트 풀링 등의 방법을 사용할 수 있습니다. 또한, List String의 재사용(데이터 읽기, 쓰기 처리) 등도 고려해야 합니다. 하지만, 이 모든 것들은 메모리 이슈를 감안하면서, 메모리와 CPU 성능 중 어떤 것을 우선할지를 고려하여 사용해야 합니다.

3. 프로그램의 안정성과 예측 가능성

메모리 누수 방지 : 스택과 힙의 올바른 사용은 메모리 누수를 방지하는 데 도움이 됩니다. 메모리 누수는 프로그램의 안정성을 저하시키고 예측 불가능한 동작을 유발할 수 있습니다.
메모리 누수에 관해서는 아래의 페이지에 따로 정리해놓았습니다.
스택 오버플로우 방지 : 스택 메모리는 제한된 크기를 가지며, 이를 초과할 경우 스택 오버플로우가 발생합니다. 이를 방지하려면 스택의 한계를 이해하고 적절하게 관리해야 합니다.
일반적으로 이 부분은 C#으로 알고리즘을 풀 때 만날 수 있습니다.
윈도우, AOS, IOS는 기본적으로 1MB로 설정되어 있으며, 버전과 사용 환경에 따라 값이 다를 수 있습니다.

4. 오류 해결과 디버깅

문제 해결 : 메모리 관련 오류는 디버깅하기 어려울 수 있습니다. 스택과 힙의 작동 방식을 이해하면 이러한 오류를 더 쉽게 식별하고 해결할 수 있습니다.
메모리 프로파일링 : 성능 문제를 해결하거나 메모리 사용 패턴을 분석할 때, 스택과 힙의 사용 패턴을 이해하는 것이 중요합니다.

5. 좋은 프로그래밍 습관

코드 최적화 : 메모리 관리를 이해함으로써 더 효율적이고 최적화된 코드를 작성할 수 있습니다.
응용 프로그램 설계 : 메모리 관리는 애플리케이션의 전반적인 설계와 아키텍처에 영향을 미칩니다. 이를 이해함으로써 더 견고하고 확장 가능한 시스템을 설계할 수 있습니다.

스택 메모리

정의 : 스택 메모리는 함수 호출과 로컬 변수를 관리하는데 사용됩니다. 이는 자동으로 할당 및 해제되며, Last In First Out (LIFO) 방식으로 운영됩니다.
함수 또는 함수 내의 괄호 문, for문 등에서도 변수는 해당 로직이 실행, 종료된 후, 자동으로 할당 및 해제됩니다.
특징 : 빠른 접근 속도, 크기가 제한적, 자동 메모리 관리
사용 예시 : 기본 데이터 타입(int, float, char 등)이나 구조체(Struct)는 스택 메모리에 저장됩니다.
void ExampleFunction() { int localVariable = 5; // 스택 메모리에 저장됨 }
C#
복사

힙 메모리

정의 : 힙 메모리는 동적으로 할당되는 메모리 영역으로, 객체와 배열과 같은 참조 타입의 데이터에 사용됩니다. 개발자가 직접 할당 및 해제를 관리해야 합니다.
특징 : 느린 접근 속도, 크기가 유연함, 수동 메모리 관리
사용 예시 : 클래스(객체)는 힙 메모리에 저장됩니다.
여기서 중요한 점은 객체가 힙 메모리에 저장된다는 것이며, 주소가 아닙니다!
public class MyClass { public int Value; } void ExampleFunction() { MyClass myObject = new MyClass(); // 힙 메모리에 할당됨 myObject.Value = 10; }
C#
복사

참고 사항

가비지 컬렉션 : 유니티(C#)에서 힙 메모리는 가비지 컬렉터에 의해 관리됩니다. 더 이상 사용되지 않는 객체는 가비지 컬렉터가 자동으로 메모리를 해제합니다.

스택, 힙 메모리 할당에 대한 자세한 이해

스택과 힙 메모리를 완벽하게 이해하기 위해서는 위의 설명만으로는 부족합니다.
실제로 저도 현업에서 일하면서 이 부분을 이해하기 위해 계속 생각해봐야 했습니다.
스택과 힙 메모리의 사용에 대해 가장 잘 이해하는 방법은 실제 사용 예시를 보는 것입니다.
public class MyClass { public int Number; public MyClass(int number) { Number = number; } } public class Program { public static void CreateObject() { MyClass myObject = new MyClass(10); // 객체 생성 Console.WriteLine(myObject.Number); // 객체 사용 } public static void Main(string[] args) { CreateObject(); // CreateObject 함수 호출 } }
C#
복사
처음 메인 부분부터 살펴 보겠습니다.
1.
CreateObject 함수 호출
a.
Main 함수 내에서 CreateObject를 호출했습니다. 이 때, 함수 실행 정보는 스택에 저장됩니다.
2.
힙 메모리에 객체 할당
a.
new MyClass(10)를 호출하면, MyClass 인스턴스가 힙 메모리에 생성됩니다. 이 객체는 Number라는 정수 값을 저장하고 있습니다.
b.
이 때 MyClass의 주소는 스택에 저장됩니다.
c.
MyClass의 Int Number 또한 힙 메모리에 저장됩니다.
using System; using System.Collections.Generic; public class Program { public static void Main() { CreateAndPrintList(); } public static void CreateAndPrintList() { // List<int>를 지역변수로 생성 List<int> numberList = new List<int>(); // 리스트에 요소 추가 numberList.Add(1); numberList.Add(2); numberList.Add(3); // 리스트의 요소 출력 foreach (int number in numberList) { Console.WriteLine(number); } } }
C#
복사
처음 메인 부분부터 살펴 보겠습니다.
1.
CreateAndPrintList함수 호출
a.
Main 함수 내에서 CreateAndPrintList를 호출했습니다. 이 때, 함수 실행 정보는 스택에 저장됩니다.
2.
numberList 선언 및 new List<int>() 할당.
a.
numberList라는 List<int> 변수를 할당합니다. 이 때, numberList의 주소는 스택에, 값은 힙에 저장됩니다.
3.
numberList.Add
a.
마찬가지로, 각 요소들의 주소와 값들은 numberList 의 배열 내부 즉, 힙 내부에 쌓이게됩니다.
b.
즉, 현재 numberList에 대해서만 설명하자면
i.
numberList 변수 스택에 할당 및 객체(배열)을 힙에 생성
ii.
numberList.Add 각각의 요소들을 numberList의 힙에 생성된 배열에 할당.

스택, 힙 메모리의 정확한 이해

스택과 힙 메모리는 코드가 길어질수록 이해하기 어려워질 수 있습니다.
실제로, 위의 코드는 현업에서 볼 때 매우 짧은 부분에 속합니다.
스택과 힙 메모리가 어떻게 할당되는지를 완벽하게 이해할 필요는 없지만, 메모리 프로파일링에서 문제가 발생했을 때 이를 어떻게 해결할지는 알아야 합니다.