Home [C#] "unsafe"로 포인터 사용하기
Post
Cancel

[C#] "unsafe"로 포인터 사용하기

0. 서론

C#에서는 개발자가 포인터를 사용하지 못하도록 막고 있다.

그래서 포인터란 개념이 존재하지 않는데 이러다 보니 주소값을 확인하고 싶을 때 (예를 들어, 객체를 복사할 때 얕은 복사인지 깊은 복사인지) 방법이 없어 난감해진다.

이걸 알고 있는지 C#에서도 포인터 사용을 아예 막은 건 아닌데 어떻게 사용할 수 있는지 확인해 보자 

1. unsafe 코드

C#의 기본은 safe 코드로 동작하고 있다.

말 그대로 “안전한” 코드인데

여기서 “안전하다”의 의미는 “개발자가 메모리에 직접 액세스할 수 없다”는 의미이다.

그러므로, unsafe코드란

개발자가 메모리에 직접적으로 접근(액세스)할 수 있는 코드를 의미한다.

그래서 unsafe 코드에서는 포인터, 메모리 블록 할당 및 해제, 함수 포인터와 같은 메모리에 직접적으로 접근하는 코드를 사용할 수 있다.

1-1. unsafe 코드 활성화

Visual Studio 2019 기준으로 설명하고 있습니다.

  1. [탭] 프로젝트
  2. “프로젝트명” 속성
  3. 빌드
  4. “안전하지 않은 코드 허용” 활성화

1-2. 사용법

사용법은 크게 2가지 있다.

  1. 메서드에 unsafe를 선언
  2. 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를 사용할 수 있다.
        }
    }
}

참고 문헌

fixed 문 - 이동 가능한 변수 고정

unsafe 키워드 - C# 참조

안전하지 않은 코드, 데이터에 대한 포인터, 함수 포인터

This post is licensed under CC BY 4.0 by the author.