获取指向字节数组的指针的不安全方法

时间:2012-04-09 16:24:49

标签: c# pointers unsafe

此行为在C#中有效

public class MyClass
{
    private byte[] data;
    public MyClass()
    {
        this.data = new byte[1024];
    }
    public unsafe byte* getData()
    {
        byte* result = null;
        fixed (byte* dataPtr = data)
        {
            result = dataPtr;
        }
        return result;
    }
}

5 个答案:

答案 0 :(得分:17)

如果您要关闭安全系统,那么您有责任确保程序的内存安全。一旦你这样做,你需要安全地完成所有事情而不需要安全系统帮助你。这就是“不安全”的含义。

正如C#规范明确指出:

  

只能使用固定语句获取可移动变量的地址,并且该地址仅在该固定语句的持续时间内有效。

您正在获取可移动变量的地址,然后在fixed语句的持续时间之后使用它,因此该地址不再是有效。因此,您特别要求不能正确地执行您正在做的事情

在深入了解必须遵循的规则之前,不应编写任何不安全的代码。首先阅读规范第18章的所有内容。

答案 1 :(得分:11)

这段代码编译得很好,但会导致运行时问题。代码基本上是走私指向堆中未固定对象的指针。移动MyClass类型的下一个GC也会移动data引用,而getData之前返回的任何值现在都将指向错误的位置。

var obj = new MyClass();
unsafe byte* pValue = obj.getData();
// Assuming no GC has happened (bad assumption) then this works fine
*pValue = 42;

// Assume a GC has now happened and `obj` moved around in the heap.  The 
// following code is now over writing memory it simply doesn't own
*pValue = 42;

最后一行是否导致应用程序崩溃,覆盖另一种类型的string值,或者只是将值戳入未初始化的数组中,而只是搞砸了数学问题?你不知道。最好的结果是代码只是快速崩溃,但在所有可能的情况下,它会做一些更微妙和邪恶的事情。

答案 2 :(得分:2)

您可以使用Marshal.StructureToPtr()方法代替不安全的魔法:)

  

StructureToPtr将结构内容复制到预分配   ptr参数指向的内存块。

Marshal.StructureToPtr Method (Object, IntPtr, Boolean)

答案 3 :(得分:1)

此代码不起作用(它将编译但在运行时会导致问题)。 fixed区域结束后,数据将不再固定。

答案 4 :(得分:0)

不,一旦你离开fixed块,result的值就不再有效了(如果GC没有运行,它可能同时有效)。

执行此类操作的正确方法是在非托管内存中引用可通过C#代码访问的byte[],或将托管阵列复制到非托管内存中。