[Unity]/[C#]

[C#] 메모리(+ 가비지)

극꼼 2022. 5. 13. 11:56
반응형


1. C# 메모리 구조

2. C# 메모리 관리


1. C# 메모리 구조

메모리의 영역에는 4가지가 있습니다.

Stack 영역 지역 변수, 매개 변수를 저장. 컴파일 시점에 크기를 할당하는 정적 할당을 사용
Heap 영역 사용자 관리 영역. 사용자 정의에 의해 할당된 메모리를 저장하거나 해제하는 동적 할당을 사용
Data 영역 전역 변수, static 변수를 저장. 컴파일 시점에 크기 할당.
Code 영역 소스 코드, 기계어로 제어되는 메모리 영역.

크게 스택 영역과 힙 영역으로 나뉘는데요, 스택영역은 관리되지 않는 공간, 힙영역관리가 되는 공간입니다.

 

* 관리 = 사용하지 않는 메모리를 스스로 해제하고, 다른 메모리가 올라갈 수 있게 하는 것.

이때, 메모리를 정리하는 일을 하는 것이 가비지 컬렉터입니다. 가비지 컬렉터는 자주 호출되면 메모리 공간을 정리하기 위해 리소스를 많이 사용하기 때문에 성능이 많이 떨어집니다. 

 

1) 스택영역

: 일반적인 값 형식인 int, char, bool 등이 있으며, 사용자가 선언한 struct도 값 형식으로 스택영역에 저장됩니다. 함수를 빠져나가면 자동으로 메모리가 해제되기 때문에 관리할 필요가 없습니다. 

 

* stack overflow (스택 오버플로우) : 과도한 재귀, 너무 큰 지역 변수를 선언하게 되면 할당된 스택 내에 stack frame이 과도하게 쌓여 stack 영역을 초과하게 되면서 다른 메모리 영역을 침범하는 현상.

* stack frame : 매개 변수, 반환 주소 값, 함수의 호출 정보(지역 변수 등)

 

2) 힙영역

: 프로그램이 실행될 때까지 알 수 없는 가변적인 양의 데이터를 저장하기 위해 프로그램 프로세스가 사용할 수 있게 미리 예약된 메인 메모리 영역입니다. 

참조 형식이 추가되는 메모리 공간입니다. 참조 형식의 변수는 스택영역과 힙영역을 동시에 이용하는데, 스택영역에는 데이터의 주소를, 힙영역에는 데이터의 값을 저장합니다. 코드 블록이 끝나면 스택에 있는 데이터의 주소는 사라지지만 힙영역에 존재하는 데이터의 값은 남게 되고, C#에서는 가비지 컬렉터가 주기적으로 힙을 청소합니다. 

 

 

2. C# 메모리 관리

- C#의 메모리 관리 장점

: 메모리 해제에 신경쓰지 않아도 됩니다. 이미 삭제된 메모리 또는 엉뚱한 메모리에 접근하지 않게 해줍니다.

 

- 가비지 컬렉터 (Garbage Collector)

: 힙영역에서 사용하지 않는 메모리를 정리. 

* 가비지 (Garbage) : 더 이상 참조되지 않는 메모리

 

* 가비지가 발생하는 예시)

1) + operator로 문자열을 조합할 때.

string output = "[" + index.ToString() + "]" + name;
//각각의 string 인스턴스가 생성되기 때문에 가비지가 많이 생성.

//StringBuilder는 문자열을 조합할 때 새로운 객체를 생성하지 않는다.
StringBuilder sb = new StringBuilder();
sb.Append("[");
sb.Append(index);
sb.Append("]");
sb.Append(name);

 

2) 메서드 안에서 생성한 객체.

public class SaveData1 //클래스일 경우
{
    public int data;
    public SaveData1(int data)
    {
        this.data = data;
    }
}

public struct SaveData2 //struct일 경우
{
    public int data;
    public SaveData2(int data)
    {
        this.data = data;
    }
}

public void print(float x)
{
    SaveData1 sd1 = new SaveData1(100);
    SaveData2 sd2 = new SaveData2(200);
    Console.WriteLine(sd1.data);
    Console.WriteLine(sd2.data);
}

메서드가 끝났을 때, new로 생성된 클래스 인스턴스는 더 이상 사용하지 않는 가비지가 됩니다.
반면, 구조체를 new로 인스턴스를 만들었을 경우 값타입이기 때문에 스택 영역에 메모리가 할당되며 메서드를 빠져나가면 자동으로 삭제됩니다.

 

3) Boxing.

: 값타입의 객체를 참조타입 객체로 포장하는 과정입니다. 많은 계산 과정이 필요하며, 박싱 과정에서 힙에 메모리를 할당하게 되며 가비지를 생성합니다.

 

 

반응형

'[Unity] > [C#]' 카테고리의 다른 글

[C#] 구조체(struct)  (0) 2022.05.16
[C#] 인터페이스  (0) 2022.05.15
[C#] Nullable (feat. int?)  (0) 2022.02.04
[C# 기초] #21. 힙(Heap)  (0) 2022.01.30
[C# 기초] #20. 트리(Tree), 이진트리, 이진 탐색 트리  (2) 2022.01.29