0. 서론
C#에서는 개발자가 포인터를 사용하지 못하도록 막고 있다.
그래서 포인터란 개념이 존재하지 않는데 이러다 보니 주소값을 확인하고 싶을 때 (예를 들어, 객체를 복사할 때 얕은 복사인지 깊은 복사인지) 방법이 없어 난감해진다.
이걸 알고 있는지 C#에서도 포인터 사용을 아예 막은 건 아닌데 어떻게 사용할 수 있는지 확인해 보자
1. unsafe 코드
C#의 기본은 safe 코드로 동작하고 있다.
말 그대로 “안전한” 코드인데
여기서 “안전하다”의 의미는 “개발자가 메모리에 직접 액세스할 수 없다”는 의미이다.
그러므로, unsafe코드란
개발자가 메모리에 직접적으로 접근(액세스)할 수 있는 코드를 의미한다.
그래서 unsafe 코드에서는 포인터, 메모리 블록 할당 및 해제, 함수 포인터와 같은 메모리에 직접적으로 접근하는 코드를 사용할 수 있다.
1-1. unsafe 코드 활성화
Visual Studio 2019 기준으로 설명하고 있습니다.
- [탭] 프로젝트
- “프로젝트명” 속성
- 빌드
- “안전하지 않은 코드 허용” 활성화
1-2. 사용법
사용법은 크게 2가지 있다.
- 메서드에 unsafe를 선언
- unsafe 블록
두 가지를 한번에 확인해 보자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static void Main(string[] args)
{
// 2. unsafe 블록
unsafe
{
int num = 10;
AddOwn(&num);
Console.WriteLine(num);
}
}
// 1. 메서드에 unsafe 처리
static unsafe void AddOwn(int* num)
{
*num += *num;
}
불안정한 unsafe 메서드를 호출하기 위해서는 unsafe 블록을 통해서 호출해야 한다.
2. fixed
위에서 unsafe 코드에 대한 정의를 아래와 같이 설명했다.
그러므로, unsafe코드란
개발자가 메모리에 직접적으로 접근(액세스)할 수 있는 코드를 의미한다.그래서 unsafe 코드에서는 포인터, 메모리 블록 할당 및 해제, 함수 포인터와 같은 메모리에 직접적으로 접근하는 코드를 사용할 수 있다.
즉,
unsafe코드에서는 메모리에 직접적으로 접근할 수 있는데
C#은 가비지 컬렉션을 이용해서 메모리를 정리하고 재배치할 수 있기에 문제가 발생할 수 있다.
그래서 C#에서는 fixed 문을 지원한다.
fixed란
- 가비지 컬렉션이 이동 가능한 변수를 재배치하지 못하게 하고 변수에 대한 포인터를 선언
- 문이 실행되는 동안 변수의 주소는 고정
- 선언된 포인터는 fixed문 안에서만 사용 가능
- 선언된 포인터는 읽기 전용
- unsafe에서만 사용 가능
1
2
3
4
5
6
7
8
9
10
11
12
static void Main(string[] args)
{
unsafe
{
string str = "Hello";
fixed(char* c = str)
{
// fixed 블록에서 c를 사용할 수 있다.
}
}
}
참고 문헌