본문 바로가기

TechLog

c#에서 포인터를, unsafe

c#에서 포인터를, unsafe

unsafe 키워드를 사용해야 할 일이 그렇게 많지는 않겠지만, WinAPI를 다뤄야 한다면 피해갈 수 없는 부분이므로 소개해 봅니다.

 

 

물론 닷넷을 사용하면서 포인터를 사용한다는 것은 닷넷의 철학에 역행하는 일이 되겠습니다만, 어쨌든 winapi를 호출한다던가 할 일이 있다면 포인터를 사용해야만 합니다. 이 아티클은 포인터를 사용하기 위한 키워드인 unsafe, unsafe를 사용한 코드를 컴파일하는 방법에 대해 설명합니다.

 

 

우리는 포인터가 필요하다

 

Kenial 은 처음으로 c/c++을 공부하는 사람이 가장 이해하기 어려운 부분이 포인터가 아닐까. 라고 생각한다. 시스템에 접근할 수 있는 가장 저수준의 도구이면서, '기계의 입장에서' 생각하지 않으면 도저히 이해할 수 없는 부분이 아닐까.

 

사 실 포인터 없이도 좋은 프로그램을 만들 수는 있다. 하지만 우리는 아직도 WinAPI를 벗어날 수 없고, WinAPI와 상호작용할 수 있는 코드를 만들고 싶다면, 포인터는 필요하다. 물론 포인터 없이도 가능한 일이기는 하지만, 그만큼 코드가 늘어난다거나 지저분한 코드를 얻게 되는 등의 댓가를 치뤄야 하므로...

 

 

unsafe 키워드

 

msdn c# programmer's reference를 참고하면, unsafe를 이렇게 설명하고 있다 :

 

    The unsafe keyword denotes an unsafe context, which is required for any operation involving pointers.

 

말 그대로, unsafe한 내용을 표시할 때 사용되는 키워드이다. 일단 간단한 다음 코드를 보자

 

 

 

 

int a;
int *b = &a;

 

 

 

 

a를 참조하는 포인터 변수 b를 선언하는 코드이다. c#에서 & *이 횡행하는 코드를 봐서 당황스러울 수는 있겠으나, 막상 컴파일을 해 보면 문법 에러는 발생하지 않는다. 다음과 같은 에러가 발생할 것이다 : 포인터는 안전하지 않은 컨텍스트 안에서만 사용할 수 있습니다.

 

여기서 말하는 안전하지 않은 컨텍스트'를 만드는 기능을 가진 키워드가 바로 unsafe인 것이다. 다음과 같이 코드를 고치고 다시 컴파일 해 보도록 하자 :

 

 

 

 

unsafe {
    int a;
    int *b = &a;    
}

 

 

 

 

잘 컴파일되는가? 천만의 말씀이다. 이번에는 이런 에러가 발생할 것이다 : 안전하지 않은 코드는 /unsafe를 사용하여 컴파일하는 경우에만 나타날 수 있습니다.

 

기본적으로 마이크로소프트에서는 '안전하지 않은 코드' 를 사용하는 것을 무척이나 싫어하는게 아닐까 하는 생각이 든다. (물론 정말 '안전하지 않은 코드'라고 한다면 당연하지만..) unsafe 키워드를 사용한 프로그램은 컴파일러에서 /unsafe 옵션을 주어야 하며, 이는 프로젝트 속성을 바꿔주면 된다.

 

 

clip_image001

'안전하지 않은 코드 블록 허용' 항목을 true로 세팅한다.

 

이와 같이 설정을 바꾸면 코드가 제대로 컴파일되는 것을 확인할 수 있을 것이다.

 

 

unsafe 선언의 여러 형태

 

unsafe는 위와 같이 코드 블록에만 사용할 수 있는 것은 아니다.

 

 

 

 

unsafe private void ThisIsUnsafeFunction( void* pvVoid )
{
    ...
}

 

unsafe class UnsafeClass
{
        //...
}

 

unsafe delegate void* UnsafeEventHandler ( int* i );

 

unsafe event UnsafeEventHandler UnsafeEvent;

 

 

 

 

 

보시다시피, 함수나 클래스, 딜리게이트, 이벤트까지 사용 가능하다. 딜리게이트의 경우, 이벤트 핸들러의 파라메터나 리턴 값이 포인터일 경우에 unsafe 키워드를 사용해야 한다.

  

 

정리

 

포인터를 사용하기 위한 키워드인 unsafe에 대하여 간단히 알아보았습니다. 하지만 예전 c/c++ 처럼 포인터를 사용해서 객체를 전달하는 것 같은 일을 간단하게 수행할 수는 없고, 여러가지 제약이 있습니다. 물론 이것도 피해가는 방법이 있습니다만, 일단은 천천히 소개하기로 하죠.

 

그럼 : )