1. 데이터 타입
IntPtr
IntPtr 형식은 그 크기가 플랫폼마다 고유한 정수로 디자인 되었다. 즉, 이 형식의 인스턴스는 32비트 하드웨어 및 운영 체제에서는 32비트로, 64비트 하드웨어 및 운영 체제에서는 64비트여야 한다.
IntPtr 형식은 포인터를 지원하는 언어에서 사용할 수 있으며, 포인터를 지원하는 언어와 포인터를 지원하지 않는 언어 사이에서 데이터를 참조하는 일반적인 방법이 된다.
핸들을 보관하는 데도 IntPtr 개체를 사용할 수 있다. 예를 들어, IntPtr의 인스턴스는 파일 핸들을 보관하기 위해 System.IO..::.FileStream 클래스에서 광범위하게 사용된다.
IntPtr 형식은 CLS 규격이지만, UIntPtr 형식은 그렇지 않다. 공용 언어 런타임에서는 IntPtr 형식만 사용된다. UIntPtr 형식은 IntPtr 형식과의 구조적 대칭을 유지하기 위해 주로 사용된다.
IntPtr 은 관리되지 않는 코드(Unmanaged Code) 에서는 void * 타입이다.
관리되는 코드에서 IntPtr 을 보게된다면 이렇게 생각하면 될 것 같다.
"IntPtr, 관리되지 않는 메모리 블록에 대한 포인터"
관리되는 코드에서 편리하게 사용하기 위해, 또 혹시 모를 오류의 가능성을 피하기 위해 관리되지 않는 메모리 블록의 데이터를 관리되는 데이터 블록으로 변환해 주자. Marshal 의 메소드를 이용하면 된다.
2. Marshal.PtrToStructure
관리되지 않는 메모리 블럭의 데이터를 지정된 형식의 새로 할당된 관리되는 개체로 마샬링한다.
자세한 내용은 MSDN 참조 (Marshal.PtrToStructure 메서드 (IntPtr, Type))
[ComVisibleAttribute(true)]
public static Object PtrToStructure (
IntPtr ptr,
Type structureType
)
structureType 는 형식이 지정된 클래스나 구조체여야 한다. 즉, 참조 타입, 값 타입 모두 가능하다. 다만 레이아웃이 sequential 또는 Explicit 로 설정되어 있어야 한다. 값 형식이 전달될 경우 반환값은 boxing 된 인스턴스이다. 리턴값이 object 타입이므로 사용할 때는 사용하려는 타입으로 형변환 하여 사용해야 한다.
3. Marshal.Copy
관리되는 배열에서 관리되지 않는 메모리 포인터로 데이터를 복사 또는, 관리되지 않는 메모리 포인터에서 관리되는 배열로 데이터를 복사한다. 자세한 내용은 MSDN 참조 (Marshal.Copy 메서드)
메서드의 인수 중에서 복사될 곳을 가리키는 인수는 반드시 메모리 생성 되어 있어야 한다. 즉, 관리되는 배열이라 new 연산자로 먼저 메모리 할당을 해야 하고, 관리되지 않는 배열이라면 Marshal.AllocHGlobal 등으로 메모리를 먼저 할당해주어야 한다. 그렇지 않으면 ArgumentNullException 이 발생한다.
4. Marshal.AllocHGlobal
프로세스의 관리되지 않는 메모리에서 메모리를 할당한다. 사용할 상황은 이렇다. 관리되는 코드의 데이터를 관리되지 않는 메모리 블록에 복사해야 한다. 그럴때 이 메소드를 사용한다.
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public static IntPtr AllocHGlobal(
int cb
)
cb 는 요청된 메모리의 바이트 수 이다. IntPtr 은 관리되지 않는 메모리 블록에 생성된 메모리를 가리키는 IntPtr 값이다.
여기서 중요한 것은 관리되지 않는 메모리에 우리가 직접 메모리를 생성하였으므로 수동으로 직접 메모리를 해제시켜줘야 하며 Marshal.FreeHGlobal 을 이용하면 된다.
Marshal 메소드 중에서 메모리 할당 API 는 Marshal.AllocHGlobal, Marshal.AllocCoTastMem 이렇게 2가지가 있다. AllocCoTastMem 메소드는 kernel32.dll 로 부터 LocalAlloc Win32 API 를 호출한다고 한다.
출처: https://six605.tistory.com/426 [As time goes by:티스토리]
'프로그래밍 언어 > C#' 카테고리의 다른 글
[C#] IsNullOrEmpty와 IsNullOrWhiteSpace의 차이점 (0) | 2024.11.10 |
---|---|
[C#] 포인터 관련 unsafe fixed 키워드 (0) | 2024.05.23 |
[C#] 관리되는, 관리되지 않는 코드 (0) | 2024.05.22 |
[C#] DLL 파일 생성, 참조하는 법 (0) | 2024.05.22 |
[C#] Newtonsoft.Json 사용방법 (0) | 2024.03.05 |