请参阅下面的代码段。
private void MyMethod()
{
IntPtr myVar = Marshal.AllocHGlobal(1024);
string hello = "Hello World";
Marshal.Copy(hello.ToCharArray(), 0, myVar, hello.Length);
//I don't see Hello World here. Instead, I see a memory address. WHY???
Debug.Print(myVar.ToString());
Marshal.FreeHGlobal(myVar);
}
我做错了什么?我希望能看到#34; Hello World",但我不会。
答案 0 :(得分:4)
当然你会看到一个内存地址。您刚刚将字符串复制到非托管内存,并打印出IntPtr对象的字符串表示,这是一个内存地址。指针不告诉.NET框架期望什么类型 - 它是非托管数据。
如果要从非托管内存中读取数据,则需要将该数据封送回托管字符串。
答案 1 :(得分:2)
IntPtr
是一个无类型指针。编译器和运行时都不知道它背后的内容。因此ToString()
IntPtr
上的IntPtr
的实现必须执行具有含义的内容,无论指针指向什么。因此,它返回IntPtr ptr = Marshal.StringToHGlobalUni("Hello World");
变量的数值。
确实,该方法的documentation非常清楚:
将当前IntPtr对象的数值转换为其等效的字符串表示形式。
对于它的价值,复制到非托管内存的代码充其量是危险的。它不复制空终止符。而且代码不是必需的,因为框架已经提供了现成的方法Marshal.StringToHGlobalUni
。
{{1}}
如果您希望获取字符串后面的文字,请拨打Marshal.PtrToStringUni
。显然,只有在修复缺少的空终止符时,这才是实用的。
答案 2 :(得分:0)
应该使用Marshal.StringToHGlobalUni或Marshal.StringToHGlobalAuto()。
在这里你可以看到你的字符串
Debug.Print(Marshal.PtrToStringAuto(myVar的));