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

这种行为在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; } } 

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

正如C#规范明确指出:

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

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

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

这段代码编译得很好但会导致运行时问题。 代码基本上是走私指向堆中未固定对象的指针。 移动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值,或者只是将一个值戳入未初始化的数组中,然后搞砸了数学问题呢? 你不知道。 最好的结果是代码只是快速崩溃,但在所有可能的情况下它会做一些更微妙和邪恶的事情。

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

StructureToPtrStructureToPtr的内容复制到ptr参数指向的预分配内存块。

Marshal.StructureToPtr方法(对象,IntPtr,布尔)

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

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

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