Visual c++ 如何在将托管字符串转换为UTF-8编码的非托管字符*后释放内存?
我不熟悉C++/CLI,因此不确定在使用以下代码时如何释放内存(获得了解决方案并进行了一些修改):Visual c++ 如何在将托管字符串转换为UTF-8编码的非托管字符*后释放内存?,visual-c++,utf-8,c++-cli,Visual C++,Utf 8,C++ Cli,我不熟悉C++/CLI,因此不确定在使用以下代码时如何释放内存(获得了解决方案并进行了一些修改): 我也不熟悉Visual C++,但根据 固定指针不能用作:[……]函数的返回类型 我不确定当函数结束时指针是否有效(即使它伪装成char*)。 似乎您在函数中声明了一些要传递给调用作用域的局部变量。但是,当您从函数返回时,这些局部变量可能会超出作用域。 也许你应该重新考虑一下你首先要达到的目标是什么 注意,在本文中引用了一个std::string(按值传递,即按副本传递)作为返回参数 std::s
我也不熟悉Visual C++,但根据 固定指针不能用作:[……]函数的返回类型 我不确定当函数结束时指针是否有效(即使它伪装成
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 managedStringToStlString(系统::字符串^s)
{
编码^u8=编码::UTF8;
数组^bytes=u8->GetBytes(s);
pinptr pinnedPtr=&字节[0];
返回字符串((char*)pinnedPtr);
}
因此,不会将任何局部变量传递到它们的作用域之外。该字符串由copy作为非托管std::string
处理。这正是建议的
当您以后需要const char*
时,您可以使用该方法获取一个。注意,您还可以使用将std::string
写入文件。
这是您的选项吗?Hans Passant的评论是正确的,垃圾收集器可以在内存中移动返回的指向缓冲区的指针。这是因为,当函数堆栈展开时,pin_ptr将解锁指针 解决办法是
char*ManagedStringToUnmanagedUTF8Char(字符串^str)
{
//从System::String获取缓冲区并将其固定
pin_ptr wch=PtrToStringChars(str);
//获取所需的字节数
int nBytes=::宽图表多字节(CP_UTF8,NULL,wch,-1,NULL,0,NULL,NULL);
断言(n字节>=0);
//在C++中分配GC无法移动的内存
char*lpszBuffer=新字符[n字节];
//将缓冲区初始化为空
零内存(lpszBuffer,(N字节)*大小(字符));
//将wchar_t*转换为char*,指定UTF-8编码
n字节=::宽图表多字节(CP_UTF8,NULL,wch,-1,lpszBuffer,n字节,NULL,NULL);
断言(n字节>=0);
//返回缓冲区
返回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;
这显然是Visual C++中的某个语言扩展。该扩展无法工作,当函数返回时,数组将被取消固定。之后,垃圾收集器可以移动数组并使程序随机失败。您必须复制它。我使用该函数将UTF-8字符写入文本文件,它每次都工作,因此指针似乎不可用o函数结束时有效(幸运的是):)我想要实现的是创建一个函数,将托管.NET字符串转换为非托管字符*(必须是UTF-8),我的包装类(托管代码和非托管代码之间的边界)将大量使用它。我在网上找到了很多解决方案,这是我能找到的最简单的一个。是的,这是一个选项,你能教我如何为我的案例这样做吗?好吧,我错了,我很幸运,gc在我测试时没有收集到它。我手动调用了System::GC::Collect(),它在调用范围内变成了一些随机字符。我想我需要复制一下,但我不知道怎么做。我已经添加了你提到的问题中的建议。我想这也解决了你的问题。有关引用超出其范围的局部变量的有效性,请参阅。
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 );
}
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;