[C++] Memory Allocation / static
C와 비슷한 양상을 보인다.
스택 메모리, 힙 메모리, static 메모리로 구분된다.
메모리는 선형으로 구성돼있고 컴파일러의 판단으로 특정 부분은 스택 메모리로 사용되고 또 어떤 부분은 힙 메모리, static 메모리로 정하고 사용한다.
스택 메모리의 제일 처음에는 메인 메서드가 올라간다.
이후 메인 메서드가 함수를 호출함에 따라 메인 메서드 위로 여러 메서드들이 쌓이게 되고, 각각의 메서드들이 종료될 때 마다 스택 메모리에 선언됐던 정보들이 날아가고 메인 메서드가 종료되면 프로그램이 종료된다.
(스택에 올라간 메서드에서 if - else / for / while 문법을 사용하면 또 다시 스택을 만들어진 후 해당 지역변수들이 올라가고, 문장이 마무리되면 스택에서 pop 된다.)
C에서의 malloc 혹은 C++에서의 new 연산자를 사용해 메모리를 할당하면 해당 메모리는 스택 메모리 대신 힙 메모리에 할당된다.
보통 힙 메모리에 메모리를 할당한 후 할당된 메모리를 바로 접근하지 않고 주소값을 받아서 사용한다. (new 연산자도 주소를 반환한다)
할당할 공간의 크기를 프로그램이 실행되는 도중 계산해서 할당해주기 때문에 힙 메모리에 메모리를 할당하는 작업을 Dynamic Memory Allocation이라고 부르고, 스택 메모리에 얼마나 할당할지는 컴파일 시점에서 결정되기 때문에 Static Memory Allocation이라고 부른다.
C++ 에서도 malloc을 사용할 수 있다.
새로 도입된 new 연산자와 malloc은 객체의 생성 부분에서 차이난다.
malloc(sizeof(Node)) : malloc을 사용하면 해당 크기만큼의 메모리만 생성한다.
new Node() : new 연산자를 사용하면 해당 크기만큼의 메모리를 생성한 후 생성자를 호출해 객체를 만드는 작업까지 수행한다.
힙 메모리는 프로그램의 시작부터 끝까지 유지되고, 프로그램이 시작될 때 얼마나 사용할 지 설정되기 때문에 설정된 크기를 초과해서 사용하면 프로그램이 터지니, 잘 관리해 줘야 한다.
free와 delete 메서드를 사용해서 힙 메모리를 관리한다.
free는 C에서 malloc으로 할당된 메모리를 풀어주는 역할을 했고.. delete도 하는 역할은 비슷하다.
역시 malloc과 new와 같은 차이점이 있다. 객체의 소멸 부분에서 차이난다.
free는 공간만 지워주지만, delete는 공간을 지우고 객체의 소멸자를 호출한다.
소멸자는 ~Node() {} 처럼 클래스 이름에 ~를 붙여서 선언한다.
생성된 객체가 소멸되기 직전에 호출되니, delete 메서드가 수행되거나 스택 메모리에서 해당 객체가 제거될 때 호출된다.
물론 malloc으로 할당한 메모리를 delete로 지워줘도 되고, new로 할당한 메모리를 free로 지워줘도 되지만 객체를 제대로 처리해주자.
dangling pointer 내용은 C와 완전히 동일하다. (https://13months.tistory.com/314)
dangling pointer로 인해 여러 오류가 발생할 수 있다.
n은 힙 메모리를 가리키고 있다.
그런데 n이 가리키는 힙 메모리를 지워버리면?
n은 dangling pointer가 되고, dangling pointer를 사용 시 다양한 오류를 만날 수 있다.
1. Segmentation fault
메모리가 잘못 사용되면 발생하는 오류이다.
2. Security vulnerability
delete로 메모리를 지워주면, 그 메모리에는 어떤 데이터든지 들어갈 수 있다.
해커가 해당 메모리에 악성 데이터를 넣으면..?
3. Undefined behavior
프로그램의 동작이 표준에 정의돼있지 않다.
즉, 어떻게든 동작할 수 있어 위험하다.
Dangling Pointer와 유사한 문제로 Memory Leak 문제가 있다.
Dangling Pointer는 힙 메모리를 가리키는 포인터는 있지만, 가리키는 대상인 메모리가 없는 문제였고 Memory Leak은 힙 메모리는 있지만 해당 메모리를 가리키는 포인터가 없는 문제이다.
즉, 메모리는 유효하지만 메모리에 접근할 수 없는 상태가 됐다.
힙 메모리를 제대로 관리하기 위해 Memory Leak을 꼭 신경써서 제거해주자.
static 키워드가 붙은 요소는 프로그램이 시작될 때 한 번만 초기화되고, 프로그램의 시작부터 끝까지 유지된다.
프로그램의 시작부터 끝까지 유지된다는 점에서 힙 메모리와 비슷하지만, 힙 메모리는 Dynamic Memory Allocation으로 할당되지만 static 키워드가 붙은 요소는 그렇지 않다. (+ static은 주소 대신 값을 바로 읽어온다)
왼쪽과 같이 클래스의 멤버변수로 static 멤버를 설정했다.
static 멤버변수는 클래스가 정의될 때 한 번만 초기화되고, 해당 클래스의 모든 인스턴스와 공유된다.
즉, n1의 kNodeVersion을 바꾸면 n2의 kNodeVersion도 바뀌게 된다.
보통 컴파일 시점에 결정되는 작업들을 static하다고 표현한다. (static dispatch)
따라서 static 메서드는 아직 결정되지 않은 다른 요소들에 접근할 수 없으며 같은 static 요소들에만 접근할 수 있다. (객체에서 static 요소는 this도 사용할 수 없다)
객체를 단 한 번만 할당해야 하는 싱글톤 패턴을 구현할 때 static 키워드를 사용하기도 한다.
또 다른 예약어로는 mutable이 있다.
변할 수 있다는 의미로, 클래스에서 사용하면...
int value() const { } 메서드는 원래 멤버변수를 바꿀 수 없지만, mutable 예약어가 붙은 멤버변수는 바꿀 수 있다.
해당 함수가 몇 번 호출됐는지 확인할 때 count 변수를 mutable로 선언해서 사용할 수 있다.
'Programming Language > C++' 카테고리의 다른 글
[C++] OOP (4) Type Casting (0) | 2022.10.19 |
---|---|
[C++] OOP (3) Inheritance / 연산자 오버로딩 (1) | 2022.10.12 |
[C++] C++과 Java (1) | 2022.10.05 |
[C++] OOP (2) 함수 오버로딩 / 함수 호출 (0) | 2022.09.28 |
[C++] OOP (1) 개념 / namespace (0) | 2022.09.14 |
댓글
이 글 공유하기
다른 글
-
[C++] OOP (3) Inheritance / 연산자 오버로딩
[C++] OOP (3) Inheritance / 연산자 오버로딩
2022.10.12 -
[C++] C++과 Java
[C++] C++과 Java
2022.10.05 -
[C++] OOP (2) 함수 오버로딩 / 함수 호출
[C++] OOP (2) 함수 오버로딩 / 함수 호출
2022.09.28 -
[C++] OOP (1) 개념 / namespace
[C++] OOP (1) 개념 / namespace
2022.09.14