为什么IntPtr.ToString()返回内存地址而不是字符串?

时间:2014-04-11 10:30:08

标签: c# .net

请参阅下面的代码段。

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",但我不会。

3 个答案:

答案 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的));