기본적인 상식(내기준)은 제외
메모리가 스택에 올라갈 때는 스택 프레임(stack frame) 단위로 올라간다.
예를 들어,
void foo(int arg)
{
int a;
int b;
};
와 같은 함수가 있다면 a,b를 하나씩 추가하는게 아니라 a,b를 한 번에 묶어서 스택에 올린다.
이 때, stack frame에는 a,b 뿐만 아니라 매개변수 arg와 return address (PC가 참조하는 다음 명령어?) 와 같은 정보도 포함된다.
Class의 경우 this 포인터도 올라간다.
그렇다면 힙은 왜 쓰는가?
크게 3가지 이유가 있을 수 있다.
2번의 경우 스택 메모리는 크기가 힙에 비해 제한적이기 때문에 큰 오브젝트를 올리면
stack overflow가 발생할 수 있다.
참고로, 몇 kb정도의 메모리는 스택에 올려도 되지만 그 이상은 힙에 올리는게 좋다는 의견이 있다.
int a;
int b;
int * ptr1 = new int;
int * ptr2 = new int;
cout << "&a : " << (long)&a << endl;
cout << "&b : " << (long)&b << endl;
cout << "&ptr1 : " << (long)&ptr1 << endl;
cout << "&ptr2 : " << (long)&ptr2 << endl;
cout << "ptr1 : " << (long)ptr1 << endl;
cout << "ptr2 : " << (long)ptr2 << endl;
int * arr1 = new int[100];
int * arr2 = new int[100];
cout << "arr1 : " << (long)arr1 << endl;
cout << "arr2 : " << (long)arr2 << endl;
a,b,ptr1,ptr2 의 스택 주소는 차례대로 정렬돼 있다. 이처럼 스택 영역의 메모리는 처음 시작점부터 차례대로 쌓여진다.
(왜 4byte가 아니라 12btye씩 차이가 나는지는 모르겠다. 다만, 리눅스에서 g++ 로 컴파일한건 4byte씩 차이가 난다.)
반면에 힙 영역의 주소는 띄엄띄엄 되어 있다. 힙 영역의 주소는 컴파일러의 memory allocator의 정책에 따라 바뀐다.
스택 영역은 힙 영역에 비해 할당과 제거가 빠르다. 따라서 performance가 매우 중요하다면 가급적 스택을 사용하는게 좋을지도 모른다. 하지만 스택의 경우 큰 메모리를 할당하면 stack overflow가 발생할 수 있다.