🤔 정적 할당과 동적 할당의 차이
정적 할당(Static Allocation) | 동적 할당(Dynamic Allocation) |
컴파일 타임에 메모리 할당 | 런타임에 필요한 만큼 메모리 할당 |
미리 할당 받기 때문에 동적 할당보다 빠름 | 실핼 중 논리적으로 옳고 그름을 따져 할당 받기 때문에 느림 |
프로그램 종료 시 자동으로 메모리 반환 | 사용자가 직접 메모리 반환 해주어야 함 |
🤔 Heap 메모리 사용 조건
- 무조건 포인터를 사용해야 한다.
- 결국은 heap의 주소를 저장하는 것이기 때문
- Heap 메모리에 할당을 했다면 해제(반환)도 꼭 해주어야 한다. 필연적.
- 메모리 누수(memory leak)를 방지하기 위함. + 댕글리 포인터 방지.
- 현재는 운영체제가 해제되지 않은 메모리를 회수하지만 이는 운영체제가 문제를 복구하기 위한 작업이므로, 개발자가 정확한 할당과 해제를 해주어야 한다.
댕글링 포인터
- 반환까지 해주었지만, c언어 시절 그 주소로 다시 접근할 수 있었다.
- 문제가 되는 이유는 사용허가 내리지 않은 메모리 주소에 접근할 수 있어서이다.
- 그래서 항상 반환 함수(free)를 사용 후 변수에 NULL, nullptr을 대입해 초기화해준다.
메모리 누수(memory lick)
- heap 메모리에 올렸다가 적당히 필요 없는 시점에서 해제해주지 않아 발생한다.
- 제대로 제거해주지 않아 쌓이다 보면 프로그램이 응답하지 않거나, 강제 종료된다.
🚚 c언어의 동적 할당 2가지 함수
malloc (memory allocation) | clloc (contiguous allocation) |
먼저 나온 동적 할당 함수 | malloc 이후 나온 동적 할당 함수 |
선언 시 쓰레기 값으로 초기화 됨 | 선언 시 자동으로 0으로 초기화 됨 |
malloc (memory allocation)
void* malloc(size_t _Size); // malloc 원형
// 보이드 포인터(void*)
// 어떤 반환값이 올 지 모르기 때문에 default로 void로 설정.
int* p = (자료형*)malloc(자료형 크기); // 사용 방법
- 필요한 메모리양을 바이트 단위로 전달하면 요청한 만큼 메모리를 할당하고 해당 메모리 주소를 반환
동적 배열
int* pArray = (int)malloc(sizeof(int) * 4);
//int 자료형의 크기에서 * 4를 해주어 4byte 4개의 연속된 메모리를 할당
pArray[0] = 10;
pArray[1] = 10;
pArray[2] = 20;
pArray[3] = 30;
for(int i=0; i<sizeof(pArray); ++i)
{
cout << p[i] << ' ';
}
**=> 10 10 20 30 출력**
clloc (contiguous allocation)
void* calloc(size_t number, size_t size); // clloc 원형
int * pArray = (자료형*)clloc(크기, 개수); // 사용 방법
동적 배열
int * pArray = (int*)clloc(sizeof(int), 4);
// 인자값으로 개수를 넣어줄 수 있는데, 배열로 만들고 싶으면 2이상의 수를 넣어주면 됨
for(int i=0; i<sizeof(pArray); ++i)
cout << pArray[i] << ' ';
=> 0 0 0 0 출력
C 메모리 반환
free : 할당한 메모 공간을 반환하는 c언어 함수
- heap 메모리에 할당된 주소를 반환(해제)할 때 사용한다.
사용 예시
int* pArray = (int)malloc(sizeof(int) * 4);
free(pArray);
pArray = NULL; // 댕글리 포인터 방지
int * pArray2 = (int*)clloc(sizeof(int), 4);
free(pArray2);
pArray2 = NULL; // 댕글리 포인터 방지
🚛 C++ 동적 할당
int* pNum = new int(10); //10으로 초기화하여 heap 메모리에 할당
int* pArray = new int[4]{1,2,3,4}; // 동적 배열 크기 4에 1,2,3,4 값을 초기화 하여 heap 메모리에 할당
C++ 메모리 반환
delete : 할당한 메모 공간을 반환하는 c++언어 함수
delete pNum;
delete [] pNum; // 배열은 대괄호([])를 넣어 해제 해주어야한다.
pNum = nullptr; // 주소 초기화
- C++ 에선 메모리 해제를 해주면 자동으로 이전 주소값 말고 접근할 수 없는 주소값을 넣어 막아준다.
- 하지만 안전하게 코딩하기 위하여 초기화해준다. pNum = nullptr
메모리 누수 체크
- debug 모드에서만 확인 가능
- 아래 코드 삽입 후 디버깅
//전처리 시점
#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#ifndef DBG_NEW
#define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
#define new DBG_NEW
#endif
#endif
int main()
{
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
}
동적 할당된 변수의 주소
int main()
{
int* p = (int*)malloc((sizeof(int));
return 0;
}
- 위 main 함수 안의 p는 어느 메모리 영역에 저장되어 있고, 그 이유는?
- Stack 영역이다.
- p(int포인터) 자체는 stack메모리 할당되어 있고, heap 주소를 저장하고 있을 뿐이다.
- Stack 영역이다.
'컴퓨터 구조 > C, C++' 카테고리의 다른 글
다중 포인터란 (0) | 2024.08.16 |
---|---|
구조체 크기 계산법 및 최적화 (0) | 2024.08.12 |
const와 포인터 (0) | 2024.08.09 |
[C/C++]포인터 기초 (0) | 2024.08.04 |
[C/C++] 함수란 (0) | 2024.07.31 |