
https://github.com/POCU/COMP3200CodeSamples
<aside> 💡 목차
</aside>
걍 런타임중 동적할당한 변수는 힙에 저장된다는거 말하는거임

자 그러면 힙을 설명해야죠? 힙은 뭐냐면, 컴파일 때 컴파일러가 알고 있는 메모리 공간 이런 게 아니에요, 딱 실제로 이제 프로그램이 돌기 시작을 했는데 어 거기에 메모리가 얼마나 있느냐 이런 개념이죠? 그리고 실제 그 메모리가 남하고 공유가 되기도 할 거고 어떤 의미에서는 뭐 요즘은 버추얼 메모리 시스템 쓰니까 반드시 공유는 안 되지만 어쨌든 간에 OS가 지원하는 그 무수한 메모리가 힙이라고 보시면 돼요, 그래서 실행 도중에 내가 프로그램 실행할 때마다 OS가 달라질 수 있고 그 OS의 세팅이 달라질 수는 사실 있잖아요? 그럼 그 거기 꼽힌 실제 메모리도 다를 수가 있고, 그럼 그 큰 메모리들을 이제 그냥 쓰는 거예요, 근데 이 방대한 공간에서 내가 뭐 5메가 이제 할당 해야겠다 그러면 5메가 찾아야 돼요 그것도 연속적인 곳으로 여기서 2메가 여기서 떨어진 데서 2메가 가져와서 그거를 쓸 수가 없어요, 그렇기 때문에 연속된 메모리를 찾아야 되기 때문에 느리고요 그리고 프로그래머가 이건 직접 메모리를 해제해야 돼요,
아까 스택 포인터처럼 올라갔다가 내려가는 순간 없어지는 게 아니고 컴파일러가 딱 알아서 아 여기는 8바이트가 없어지는구나 아는 게 아니기 때문에 실제 저희가 실행 도중에 new 이렇게 해서 메모리 잡아놓은 거는 프로그래머가 지워야 돼요 그래서 그렇지 않으면 내가 깜빡 잊고 안 지우고 그 포인터 잃어버렸다, 그럼 이제 메모리 누수가 발생해서 그 포인터는 다시 못 쓰죠, 그 메모리 주소는 다시 못 쓰게 되는 그래서 메모리 누수라고 해요 C++은 언매니지드 언어이기 때문에 저희가 직접 메모리를 관리해줘야 하는 거죠 그래서 힙은 이런 차이가 있고요,
힙, 스택 봤을 때 스택을 쓸 수 있으면 무조건 스택을 쓰는 게 일단은 좋아요, 근데 실행 도중에 아 이렇게 새로 만들고 막 이래야 되는 경우도 있거든요? 또 한 함수 스코프 안에서 안 끝나고 여기저기 패스하고 해야 되고 그런 경우에는 이제 힙을 쓰기도 하죠, 아니면 함수에서 반환값으로 오브젝트를 그대로 반환하면 그 값이 복사되면서 호출자한테까지 전달도 되는데, 그 오브젝트가 너무 큰 거야 그런 경우에는 차라리 힙에 오브젝트 만들고 주소 하나 반환하는 거, 즉 4바이트 반환하는 게 큰 오브젝트 반환하면서 이제 아 그 메모리 복사 많이 하는 것보다 빠르다, 그래서 그 오브젝트 크기하고도 상관이 있어요, 오브젝트가 충분히 작으면 아 최대한 스택을 많이 쓰는 게 좋다 범위에 딱 어떤 범위에서만 쓰는 오브젝트면 더더욱 그래야 된다 그 정도 이제 기억해주세요
<aside> 💡 힙 메모리는 컴파일 시점에 크기를 알 수 없는 동적 메모리 공간입니다.
힙 메모리는 프로그램 실행 중에 필요한 만큼 메모리를 할당하고 해제할 수 있습니다.
힙 메모리의 장점은 다음과 같습니다.
힙 메모리의 단점은 다음과 같습니다.
힙 메모리는 다음과 같은 경우에 사용됩니다.
힙 메모리를 사용할 때는 다음과 같은 사항을 고려해야 합니다.
결론적으로, 스택과 힙은 각각 장단점이 있으므로 상황에 맞게 적절히 사용해야 합니다.
</aside>
<aside> 💡

이번에는 이제 힙을 알아보죠, 음 자 일단 PrintVectors()라는 이제 함수가 있고요, a, b 전달하면 이렇게 더해서 뭐하네요, 뭐 더해서 출력하나 봐요, 그렇죠? 전달하는 건 똑같고요 여기 new Vector() 해갖고 뭐 이렇게 result 한 다음에 출력을 한대요, 사실 그다지 좋은 예는 아닌 게 함수 안에서 new 이렇게 하는 게 그렇게 좋은 예는 아니에요, 이거는 이제 조금 뒤에 다시 좀 더 설명을 드리고 아 뭐 그러면 그다음부터 이제 역시 힙, 스택 바뀌는 과정을 보여드릴 건데 new 하니까 이제 힙에서 생기는 거고요 그럼 현재 스택에 함수의 영역이 있다는 건 똑같아요, 모든 함수는 스택에서 작동을 하니까, 그렇게 생각하시면 맞고요, 이 함수 영역은 함수 안에 코드가 아니라 함수에서 필요한 데이터를 담고 있는 스택이라는 거죠, 여기는 Foo() 영역, PrintVectors() 호출하면 당연히 여기에 PrintVectors()의 영역이 생길 건데, 그 외에 new가 있으니까 힙에도 뭔가 생길 거예요
</aside>
<aside> 💡

자 여기 생겼어요 여기 PrintVectors() 영역이 생겼는데, 거기 보면 5120이라는 게 갑자기 보여요, 이거는 5120에 가보면 이렇게 힙에 메모리가 잡혔죠? 이게 바로 new Vector() 이 new Vector() 하면 4바이트씩 2개 필요하니까 x, y 이렇게 8바이트 잡고 새로 생성한 메모리 주소가 5120이다 그래서 이제 5120을 result라는 변수에 대입했는데, 그 result라는 변수가 스택에 있는 거죠
</aside>
<aside> 💡

[‣](https://cybecho.notion.site/2272a493004849b5a9d11ba273e502aa) 문제 발생!
자 이렇게 해서 함수를 나가요 근데 이 영역은 없어졌어요 PrintVectors() 영역, 그렇죠? 그런데 아직도 메모리에는 남아있어요, 왜? delete를 안 해줬거든요, 그렇죠?

[‣](https://cybecho.notion.site/25de273178c448d5ba7925edb74a6f71) delete를 추가해줘야함
자 제대로 고치는 것은 여기 이렇게 보이듯이 delete를 호출해야만 아까 남아있던 여기 메모리도 같이 지워줘요 그래서 이렇게 delete 호출하는 거 잊지 말아야 한다, 반드시 생각을 하셔야죠 자 그 순서를 이제 보여 드리네요 아까 그게 얘가 아니고 delete를 바꿨다는 그 코드였고요, 이렇게 들어간 다음에 delete 호출하면 싹 지워진다 이렇게 봐주시면 돼요
</aside>
<aside> 💡 내용을 토대로 글 재구성
힙 메모리는 프로그램 실행 중에 동적으로 할당되고 해제되는 메모리 영역입니다. 스택 메모리와 달리, 힙 메모리는 컴파일 시점에 크기가 결정되지 않고 런타임에 필요에 따라 유연하게 사용할 수 있습니다.
[!note] 힙 메모리는 운영 체제가 관리하는 큰 메모리 풀에서 필요한 만큼 할당받아 사용합니다. 이는 프로그램이 실행될 때마다 사용 가능한 메모리의 양이 달라질 수 있음을 의미합니다.
| 특성 | 힙 | 스택 |
|---|---|---|
| 할당 방식 | 동적 | 정적 |
| 크기 제한 | 거의 없음 | 제한적 |
| 관리 주체 | 프로그래머 | 컴파일러 |
| 접근 속도 | 상대적으로 느림 | 빠름 |
| 메모리 누수 위험 | 있음 | 거의 없음 |
| 사용 용도 | 큰 객체, 긴 수명의 데이터 | 지역 변수, 함수 호출 |
다음은 C++에서 힙 메모리를 사용하는 간단한 예시입니다:
Vector* CreateVector(int x, int y) {
return new Vector(x, y); // 힙에 Vector 객체 생성
}
void UseVector() {
Vector* v = CreateVector(3, 4);
// 벡터 사용
delete v; // 메모리 해제
}
이 예시에서 new 키워드를 사용하여 힙에 Vector 객체를 생성하고, 사용이 끝난 후 delete를 호출하여 메모리를 해제합니다.
힙 메모리의 동작 방식을 시각적으로 이해하기 위해 다음 다이어그램을 살펴보겠습니다:
graph TD
A["프로그램 시작"] --> B["힙 메모리 할당 요청"]
B --> C{"충분한 연속 메모리 존재?"}
C -->|Yes| D["메모리 할당"]
C -->|No| E["메모리 부족 에러"]
D --> F["객체 생성 및 초기화"]
F --> G["객체 사용"]
G --> H["메모리 해제 요청"]
H --> I["메모리 해제"]
I --> J["메모리 반환"]
J --> K["프로그램 종료"]
style A fill:#0047AB,stroke:#333,stroke-width:2px,color:#FFFFFF
style B fill:#CC5500,stroke:#333,stroke-width:2px,color:#FFFFFF
style C fill:#006600,stroke:#333,stroke-width:2px,color:#FFFFFF
style D fill:#551A8B,stroke:#333,stroke-width:2px,color:#FFFFFF
style E fill:#8B0000,stroke:#333,stroke-width:2px,color:#FFFFFF
style F fill:#CC5500,stroke:#333,stroke-width:2px,color:#FFFFFF
style G fill:#0047AB,stroke:#333,stroke-width:2px,color:#FFFFFF
style H fill:#006600,stroke:#333,stroke-width:2px,color:#FFFFFF
style I fill:#551A8B,stroke:#333,stroke-width:2px,color:#FFFFFF
style J fill:#CC5500,stroke:#333,stroke-width:2px,color:#FFFFFF
style K fill:#0047AB,stroke:#333,stroke-width:2px,color:#FFFFFF
이 다이어그램은 힙 메모리의 생명주기를 보여줍니다. 메모리 할당 요청부터 해제까지의 과정을 단계별로 나타내고 있습니다.
[!important] 힙 메모리를 사용할 때는 항상 메모리 누수와 댕글링 포인터에 주의해야 합니다. new로 할당한 메모리는 반드시 delete로 해제해야 하며, 해제된 메모리를 가리키는 포인터를 사용하지 않도록 주의해야 합니다.
</aside>