我不熟悉C ++ / CLI,因此在使用下面的代码时不确定如何释放内存(得到解决方案here并稍加修改):
char* ManagedStringToUnmanagedUTF8Char( String^ s )
{
array<unsigned char> ^bytes = Encoding::UTF8->GetBytes( s );
pin_ptr<unsigned char> pinnedPtr = &bytes[0];
return (char*)pinnedPtr;
}
当我通过在文本文件中写入char来测试它时,上面的代码正在工作。如果我遗漏了某些东西(需要清理pinnedPtr?),请告诉我。
现在我使用它时:
char* foobar = ManagedStringToUnmanagedUTF8Char("testing");
//do something with foobar
//do I need to free up memory by deleting foobar here?
//I tried 'delete foobar' or free(foobar) but it crashes my program
答案 0 :(得分:0)
我也不熟悉Visual-C ++,但根据this article
固定指针不能用作:[...]函数的返回类型
我不确定指针在函数结束时是否有效(即使它伪装成char*
。
您似乎在要传递给调用范围的函数中声明了一些局部变量。 '然而,当你从函数返回时,这些可能会超出范围。
也许你应该重新考虑一下你想要实现的目标?
注意,在您引用的文章中,std::string
(通过值传递,即通过复制)被用作返回参数。
std::string managedStringToStlString( System::String ^s )
{
Encoding ^u8 = Encoding::UTF8;
array<unsigned char> ^bytes = u8->GetBytes( s );
pin_ptr<unsigned char> pinnedPtr = &bytes[0];
return string( (char*)pinnedPtr );
}
因此,没有局部变量从其范围中传出。该字符串由副本作为非托管std::string
处理。这正是this post所暗示的。
如果您稍后需要const char*
,则可以使用string::c_str()方法获取一个。请注意,您还可以使用file streams将std::string
写入文件。
这是你的选择吗?
答案 1 :(得分:0)
Hans Passant的评论是正确的,返回的缓冲区指针可以由垃圾收集器在内存中移动。这是因为,当函数堆栈展开时,pin_ptr将取消固定指针。
解决方案是
示例代码:
char* ManagedStringToUnmanagedUTF8Char(String^ str)
{
// obtain the buffer from System::String and pin it
pin_ptr<const wchar_t> wch = PtrToStringChars(str);
// get number of bytes required
int nBytes = ::WideCharToMultiByte(CP_UTF8, NULL, wch, -1, NULL, 0, NULL, NULL);
assert(nBytes >= 0);
// allocate memory in C++ where GC cannot move
char* lpszBuffer = new char[nBytes];
// initialize buffer to null
ZeroMemory(lpszBuffer, (nBytes) * sizeof(char));
// Convert wchar_t* to char*, specify UTF-8 encoding
nBytes = ::WideCharToMultiByte(CP_UTF8, NULL, wch, -1, lpszBuffer, nBytes, NULL, NULL);
assert(nBytes >= 0);
// return the buffer
return lpszBuffer;
}
现在,使用时:
char* foobar = ManagedStringToUnmanagedUTF8Char("testing");
//do something with foobar
//when foobar is no longer needed, you need to delete it
//because ManagedStringToUnmanagedUTF8Char has allocated it on the unmanaged heap.
delete foobar;