pinvoke:如何释放 malloc 字符串?
在 C dll 中,我有一个这样的函数:
char* GetSomeText(char* szInputText)
{
char* ptrReturnValue = (char*) malloc(strlen(szInputText) * 1000); // Actually done after parsemarkup with the proper length
init_parser(); // Allocates an internal processing buffer for ParseMarkup result, which I need to copy
sprintf(ptrReturnValue, "%s", ParseMarkup(szInputText) );
terminate_parser(); // Frees the internal processing buffer
return ptrReturnValue;
}
我想使用 P/invoke 从 C# 调用它。
[DllImport("MyDll.dll")]
private static extern string GetSomeText(string strInput);
如何正确释放分配的内存?
我正在编写针对 Windows 和 Linux 的跨平台代码。
编辑: 像这样
[DllImport("MyDll.dll")]
private static extern System.IntPtr GetSomeText(string strInput);
[DllImport("MyDll.dll")]
private static extern void FreePointer(System.IntPtr ptrInput);
IntPtr ptr = GetSomeText("SomeText");
string result = Marshal.PtrToStringAuto(ptr);
FreePointer(ptr);
In a C dll, I have a function like this:
char* GetSomeText(char* szInputText)
{
char* ptrReturnValue = (char*) malloc(strlen(szInputText) * 1000); // Actually done after parsemarkup with the proper length
init_parser(); // Allocates an internal processing buffer for ParseMarkup result, which I need to copy
sprintf(ptrReturnValue, "%s", ParseMarkup(szInputText) );
terminate_parser(); // Frees the internal processing buffer
return ptrReturnValue;
}
I would like to call it from C# using P/invoke.
[DllImport("MyDll.dll")]
private static extern string GetSomeText(string strInput);
How do I properly release the allocated memory?
I am writing cross-platform code targeting both Windows and Linux.
Edit:
Like this
[DllImport("MyDll.dll")]
private static extern System.IntPtr GetSomeText(string strInput);
[DllImport("MyDll.dll")]
private static extern void FreePointer(System.IntPtr ptrInput);
IntPtr ptr = GetSomeText("SomeText");
string result = Marshal.PtrToStringAuto(ptr);
FreePointer(ptr);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您应该将返回的字符串编组为 IntPtr,否则 CLR 可能会使用错误的分配器释放内存,从而可能导致堆损坏和各种问题。
看到这个几乎(但不完全)重复的问题 PInvoke for C function that returns char * 。
理想情况下,您的 C dll 还应该公开一个 FreeText 函数,供您在希望释放字符串时使用。这可确保以正确的方式释放字符串(即使 C dll 发生更改)。
You should marshal returned strings as
IntPtr
otherwise the CLR may free the memory using the wrong allocator, potentially causing heap corruption and all sorts of problems.See this almost (but not quite) duplicate question PInvoke for C function that returns char *.
Ideally your C dll should also expose a
FreeText
function for you to use when you wish to free the string. This ensures that the string is deallocated in the correct way (even if the C dll changes).添加另一个函数
ReturnSomeText
来调用free
或再次释放内存所需的任何内容。Add another function
ReturnSomeText
that callsfree
or whatever is needed to release the memory again.如果您返回使用本机 malloc 分配的 .net 内存,那么您还必须导出释放器。我不认为这是一个理想的操作,而是更喜欢将文本导出为
BSTR
。它可以由 C# 运行时释放,因为它知道BSTR
是由 COM 分配器分配的。 C# 编码变得更加简单。唯一的问题是
BSTR
使用 Unicode 字符,而 C++ 代码使用 ANSI。我会像这样解决这个问题:C++
C#
If you return to .net memory allocated with your native malloc, then you also have to export the deallocator. I don't regard that to be a desirable action and instead prefer to export the text as a
BSTR
. This can be freed by the C# runtime because it knows that theBSTR
was allocated by the COM allocator. The C# coding becomes a lot simpler.The only wrinkle is that a
BSTR
uses Unicode characters and your C++ code uses ANSI. I would work around that like so:C++
C#