[C / C++] 스택 & 힙 메모리 할당 과정
여러 변수 선언 / 동적할당 예시를 통해, 스택과 힙에 메모리가 할당되는 과정을 살펴보자.
다음 클래스를 예로 설명한다.
main 함수에서, Person 클래스 포인터 p를 선언.
스택 세그먼트에 p의 메모리를 할당함. p를 초기화해주지 않았으므로 쓰레기 주소값이 들어감.
p에 접근하려고 할 시, 초기화되지 않은 쓰레기 주소값에 접근했으므로 오류 발생.
p를 nullptr로 초기화함,
p에 접근하려 하지만, p는 null로 초기화되어 있기 때문에, 접근할 수 없으므로 오류 발생.
(정확히는 nullptr로 초기화 시, 0 주소값으로 초기화됨. 0 주소값은 보통 운영체제(OS)이므로 접근할 수 없음)
Person 클래스를 동적할당함.
힙 세그먼트에 새 메모리가 할당됨.
Person 클래스 포인터 p를 선언. 이는 동적할당이 아니므로, 스택에 메모리가 할당됨.
동적할당한 Person 클래스는 따로 힙에 메모리가 할당됨.
두 주소는 전혀 관계가 없음.
클래스 포인터를 선언하고, 이를 동적할당함.
포인터 메모리는 스택에 할당되고, 동적할당한 Person 클래스 메모리는 힙에 할당됨.
p에 접근 시, 힙 세그먼트에 있는 메모리를 수정할 수 있음.
string은 또 다른 char 타입 배열이다.
Person 클래스가 힙에 할당되어 있으므로, char 배열도 힙에 있음.
Person 클래스 수정.
int 타입 변수 추가 및 Person 클래스 생성자에서 string과 int를 입력받고, 생성자 초기화를 통해 이를 초기화해 줌.
Person 클래스 포인터 변수를 선언하고, 생성자 초기화를 통해 이름과 나이를 초기화함.
포인터는 스택에 할당되며, 동적할당한 Person 클래스는 힙에 할당됨.
p를 nullptr로 초기화함.
포인터 p의 주소값을 nullptr로 초기화한 것이므로, Person 클래스 데이터와는 무관함.
하지만, 동적할당한 Person 클래스를 가리키는 주소가 없어졌으므로, 메모리를 해제할 수 없음.
위와 같이 p를 선언함.
새로 Person 클래스를 동적할당함.
p가 가리키는 주소값을 새로 동적할당한 Person 클래스로 옮김.
처음 동적할당한 메모리를 가리키는 포인터는 사라짐. (메모리 해제 불가)
p1과 p2 포인터 변수로 각각 할당함.
int 타입 변수 선언. 스택에 할당.
int 타입 변수를 미리 선언 후, p에 접근하여 age에 값을 대입함.
이는 age의 값을 복사하여 p->age에 대입함.
두 값은 관계없음.
age의 값을 변경하더라도 서로 연결되어있지 않기 때문에, p->age에 영향 없음.
Person 클래스 수정.
다른 Person 클래스를 저장할 수 있는 변수 추가.
동적할당한 p1, p2 선언 및 초기화.
p1->partner를 p2로 초기화.
힙에 있는 p2의 주소값이 대입됨.
동적할당한 p1 선언 및 초기화.
AddFunction 함수 호출.
매개변수로 p를 넘김.
p의 주소값과 동일한 주소값을 가리키는 새 변수를 스택 메모리에 할당.
p와 동일한 주소값을 가리키고 있으므로, person->age를 변경 시, 그대로 반영됨.
함수가 끝나면, 스택에 할당된 person은 제거됨.
Person 포인터 변수 p를 선언하고, CreatePerson 함수 호출하여 반환값으로 대입함.
CreatePerson 함수에서 동적할당한 person 선언 및 초기화.
person 변수는 스택에 할당.
person을 반환.
person은 함수가 종료됨에 따라 스택에서 제거되지만, 반환된 주소값은 p에 저장됨.