이 문서에서는 C#에서의 `IntPtr`, 관리 코드(Managed Code)와 비관리 코드(Unmanaged Code)에 대해 살펴봅니다. 이들은 메모리 처리, 플랫폼 간 상호 작용, 저수준 작업을 수행할 때 매우 중요합니다.
`, `MyClass` 등의 객체는 GC가 메모리를 자동으로 회수합니다.
- 활용:
- 개발자는 비즈니스 로직에 집중하고, 복잡한 메모리 관리로부터 자유로워집니다.
- 프로그램의 견고성과 보안성이 향상됩니다.
- 모든 .NET 언어가 IL로 컴파일되어 상호 운용성을 제공합니다.
- 주의사항:
- GC는 결정적으로 동작하지 않으므로, 메모리 해제 시기가 불확실합니다.
- GC 자체에도 성능 오버헤드가 있으며, 적절한 객체 생명 주기 관리가 필요합니다.
- LOH(Large Object Heap)는 큰 객체들이 할당되며, 이를 처리할 때 주의해야 합니다.
- 비관리 자원은 명시적으로 해제해야 하며, 종료자(`Finalize`)보다는 `Dispose()` 패턴을 사용하는 것이 좋습니다.
1. 관리 코드와 자원
- 정의: - 관리 코드: .NET CLR(Common Language Runtime)에 의해 관리되고 실행되는 코드입니다(C#, VB.NET, F# 등이 IL로 컴파일됨). CLR은 다음과 같은 핵심 서비스를 제공합니다: - 메모리 관리(GC): 객체의 메모리 할당과 해제를 자동으로 처리하여 개발자가 수동으로 메모리를 관리하지 않아도 됩니다. - 타입 안전성: 타입 변환, 배열 경계 검사 등을 통해 다양한 메모리 오류를 방지합니다. - 예외 처리: 구조화된 다중 언어 예외 처리 메커니즘을 제공합니다. - JIT 컴파일: IL 코드를 런타임 시 네이티브 머신 코드로 컴파일합니다. - 관리 자원: CLR의 가비지 컬렉터가 관리하는 객체가 차지하는 메모리를 말합니다. 예를 들어, `string`, `List2. 비관리 코드와 자원
- 정의: - 비관리 코드: CLR에 의해 관리되지 않는 코드로, Win32 API, C/C++ DLL, COM 구성 요소 등이 포함됩니다. - 비관리 자원: CLR의 가비지 컬렉터에 의해 관리되지 않는 리소스로, 직접 할당 및 해제가 필요합니다. 예: 파일 핸들, 윈도우 핸들, GDI 핸들, 소켓 핸들 등. - 활용: - 운영 체제의 기본 기능에 접근하거나 효율적인 원시 코드 라이브러리를 재사용할 수 있습니다. - 고성능 계산을 위해 정밀한 메모리 레이아웃 제어나 직접적인 메모리 조작이 필요할 때 사용됩니다. - 주의사항: - 비관리 자원을 올바르게 해제하지 않으면 자원 누수가 발생할 수 있습니다. - 직접 포인터 조작이나 잘못된 데이터 마샬링은 심각한 오류를 초래할 수 있습니다. - P/Invoke 또는 COM 호출 시 데이터 타입 변환을 신경 써야 합니다. - 원시 코드는 플랫폼 의존성이 있으므로 주의가 필요합니다.3. IntPtr 구조체
- 정의: - `IntPtr`는 포인터 또는 핸들을 안전하게 저장하기 위한 플랫폼별 정수형 타입입니다. - 32비트 환경에서는 4바이트, 64비트 환경에서는 8바이트 길이를 가집니다. - `IntPtr`는 주로 관리 코드와 비관리 코드 간에 포인터 또는 핸들을 안전하게 전달하는 용도로 사용됩니다. - 활용:
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateFile(
string lpFileName,
FileAccess dwDesiredAccess,
FileShare dwShareMode,
IntPtr lpSecurityAttributes,
FileMode dwCreationDisposition,
FileAttributes dwFlagsAndAttributes,
IntPtr hTemplateFile);
IntPtr hWnd = FindWindow(null, "계산기");
IntPtr fileHandle = CreateFile("test.txt", FileAccess.ReadWrite, FileShare.None, IntPtr.Zero, FileMode.OpenOrCreate, FileAttributes.Normal, IntPtr.Zero);
IntPtr unmanagedMemory = Marshal.AllocHGlobal(1024);
Marshal.FreeHGlobal(unmanagedMemory);
- 주의사항:
- `IntPtr`로 표시된 비관리 메모리나 자원은 반드시 적절한 시점에 해제해야 합니다.
- `IntPtr`에 대한 포인터 산술 연산은 위험하므로, `unsafe` 블록 내에서만 수행해야 합니다.
- `IntPtr`의 출처를 명확히 파악하고, 필요한 경우 해제 함수를 호출해야 합니다.