1) 메모리 구조
┌──────────────────────────────┐
│ 코드(Code) 영역 │ ← 실행할 명령어 저장
├──────────────────────────────┤
│ 정적/데이터(Static) 영역 │ ← static 변수, 상수
├──────────────────────────────┤
│ 힙(Heap) │ ← 참조 타입 (클래스, 배열, 문자열)
│ ↑ ↓ (GC 관리) │
├──────────────────────────────┤
│ 스택(Stack) │ ← 지역 변수, 매개변수, 값 타입
│ (함수 호출 시 생성/해제)│
└──────────────────────────────┘
1️⃣ 스택(Stack)
- 함수가 호출될 때 스택 프레임(Stack Frame) 이 생성됩니다.
- 지역 변수, 매개변수, 값 타입(struct, int, bool, float 등) 이 여기에 저장됩니다.
- 함수가 끝나면 해당 스택 프레임이 제거되면서 자동으로 해제됩니다.
💡 특징
- 빠름 (LIFO 구조)
- 자동 해제
- 값 타입은 복사로 전달됨 (단, ref 사용 시 참조 전달 가능)
- ex) C# 구조체로 ref 키워드를 사용해서 함수에 넘길때 stack 안에 있는 주소를 가리킴
ref 사용 예시
using System;
using System.Numerics;
namespace Rookiss_CSharp
{
class Program
{
struct Mage
{
public int hp;
public int attack;
}
static void HealMage(ref Mage mage) // stack 안에 있는 Main(string[] args) -> mage 변수의 주소 가리킴
{
mage.hp += 30;
}
static void Main(string[] args)
{
Mage mage;
// Mage mage = new Mage();
mage.hp = 100;
mage.attack = 50;
HealMage(ref mage);
}
}
}
stack 예시
void Foo()
{
int x = 10; // Stack에 x=10 저장
int y = 20; // Stack에 y=20 저장
int sum = x + y; // Stack에 sum=30 저장
} // Foo 종료 시 x, y, sum 사라짐
2️⃣ 힙(Heap)
- 클래스 객체, 배열, 문자열 등 참조 타입(reference type) 은 힙에 저장됩니다.
- 변수에는 실제 데이터가 아니라 힙 메모리 주소(참조값) 가 저장됩니다.
- 가비지 컬렉터(GC)가 더 이상 참조되지 않는 객체를 자동으로 해제합니다.
💡 특징
- 상대적으로 느림 (동적 할당)
- 참조 타입이 저장됨
- 수동 해제 불필요 (GC가 관리)
참고
- 동적할당하고 해제하지 않으면 Heap에 계속 남아있음
- (C++은 직접해줘야하고, C#은 더이상 가리키는 변수가 없으면 가비지 컬렉터에 의해 자동 해제됨)
🧠 예시
class Player
{
public int hp;
}
void Main()
{
Player p1 = new Player(); // p1은 스택에, new Player()는 힙에 생성
p1.hp = 100;
}
메모리 구조:
[Stack]
p1 ─────────┐
▼
[Heap]
Player object
hp = 100
3️⃣ 정적 영역 (Static / Data Area)
- static 키워드가 붙은 변수나 상수, 전역 변수 등이 여기에 저장됩니다.
- 프로그램이 시작될 때 할당되고, 종료될 때까지 유지됩니다.
💡 특징
- 전역적으로 접근 가능
- 프로그램이 끝날 때까지 해제되지 않음
🧠 예시
class Game
{
public static int playerCount = 0;
}
- Game.playerCount는 정적 메모리 영역에 존재.
- 프로그램 종료 전까지 계속 남아 있음.
4️⃣ (참고) 상수(Constant) 영역 / 문자열 풀(String Intern Pool)
- 리터럴 상수(const, 문자열 리터럴 등)는 특별한 메모리 영역(읽기 전용 데이터 영역)에 저장됩니다.
- 문자열은 String Intern Pool에 저장되어 중복 생성 방지됩니다.
🧠 예시:
string s1 = "Hello";
string s2 = "Hello";
Console.WriteLine(object.ReferenceEquals(s1, s2)); // True
→ "Hello"는 문자열 풀에 한 번만 저장되어, 두 변수 모두 같은 주소를 참조합니다.
📌 핵심 요약
| 구분 | 저장 대상 | 생명주기 | 관리 방식 |
| Stack | 값 타입, 지역 변수 | 함수 실행 중 | 자동 |
| Heap | 참조 타입 (클래스, 배열) | 참조가 끊길 때 | GC가 해제 |
| Static 영역 | static 변수, 상수 | 프로그램 전체 | 자동 |
| String Pool | 문자열 리터럴 | 전역적 | CLR 관리 |
출처
스택과 힙 | [C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part1: C# 기초 프로그래밍 입문
스택과 힙
www.inflearn.com
37ㄱ 스택과 힙
'C# > 기본 문법' 카테고리의 다른 글
| C# static (0) | 2025.11.01 |
|---|---|
| C# 생성자 (0) | 2025.11.01 |
| C# 객체 지향 시작 및 복사와 값 참조 (0) | 2025.11.01 |
| C# TextRPG (0) | 2025.11.01 |
| C# 간단한 연습문제 (0) | 2025.10.27 |