C/C++과 C# 사이의 메모리 할당/해제 방법
C#과 C/C++ 사이의 메모리 전달에 대해서는 예전에도 다뤘는데요.
구조체 포인터 인자에 대한 P/Invoke 정의
; https://www.sysnet.pe.kr/2/0/912
C++ 측에서 메모리를 new로 할당한 경우, 그럴 때는 C# 측에서 해제를 하는 방법이 없습니다. 따라서 어쩔 수 없이 다시 C/C++ 측의 코드를 불러서 delete로 해제하는 절차를 따르게 되는데... 이것도 예전에 설명드렸습니다.
Win32 Interop - 크기가 정해지지 않은 배열을 C++에서 C#으로 전달하는 경우
; https://www.sysnet.pe.kr/2/0/737
C#과 C/C++은 서로 메모리 할당/해제하는 방식이 다르기 때문에 어쩔 수 없지만, 이런 경우 2개의 환경 모두에서 공통 메모리 할당 방법을 사용하면 이런 제약으로부터 자유로울 수 있습니다. 바로 이럴 때 뜻하지 않게 COM이 등장합니다. COM의 메모리 할당/해제는 OS에 의해 제공되는 방식이므로 C#과 C/C++의 환경적인 영향을 받지 않고 사용할 수 있습니다.
일례로, C/C++에서 이렇게 CoTaskMemAlloc API를 사용해 메모리를 할당해서 반환했으면,
void AllocBuffer(wchar_t **pBuffer)
{
wstring txt = L"fvjasdflkvsadjkfjavsdkfsadjvdksajfkavsdjflajvsdkfjalkvsjflkjewoqiur092uvoifjkladjfas";
int bufSize = txt.size() + 1;
*pBuffer = (wchar_t *)::CoTaskMemAlloc(4096);
*pBuffer[0] = '\0';
wcsncpy_s(*pBuffer, bufSize, txt.c_str(), bufSize - 1);
}
WIN32PROJECT1_API wchar_t *fnWin32Project1()
{
wchar_t *pBuffer = nullptr;
AllocBuffer(&pBuffer);
return pBuffer;
}
C#에서는 해당 포인터 변수 그대로 가져다가 Marshal.FreeCoTaskMem 메서드를 이용해 해제할 수 있습니다.
using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
[DllImport("Win32Project1.dll")]
public static extern IntPtr fnWin32Project1();
static unsafe void Main(string[] args)
{
IntPtr ptr = fnWin32Project1();
{
string txt = Marshal.PtrToStringUni(ptr);
txt = null;
GC.Collect();
}
Marshal.FreeCoTaskMem(ptr);
}
}
}
(
첨부한 파일은 이 글의 예제 코드를 포함합니다.)
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]