我在内存中有一个二进制序列化对象,我想通过使用C#中的指针(unsafae代码)从内存中读取它。 请查看以下从内存流中读取的功能。

static Results ReadUsingPointers(byte[] data)
{
    unsafe
    {
        fixed (byte* packet = &data[0])
        {
            return *(Results*)packet;
        }
    }
}

在此return *(Results*)packet; 语句我得到一个编译时异常“无法获取其地址,获取其大小或声明一个指向托管类型结果的指针”

这是我的结构

public struct Results
{
    public int Id;
    public int Score;
    public char[] Product;
}

根据我的理解,我的结构的所有属性都是可蓝调的属性,那么为什么会出现此错误?如果需要在结构中使用char []怎么办?

EDIT-1让我进一步解释(请注意,对象已被嘲笑)...

背景:我有一个Results对象数组,我使用二进制序列化对它们进行了序列化。 现在,在程序的后期,由于数据量非常大,我需要尽快对内存中的数据进行反序列化。 所以我一直在尝试,不安全的代码如何在这里帮助我。

假设我的结构中不包含public char[] Product; ,我以相当不错的速度恢复了数据。 但是使用char []会给我错误(编译器应该这样做)。 我一直在寻找一种可以在这种情况下使用char []的解决方案。

===============>>#1 票数:2

MSDN说

以下任何类型都可以是指针类型:

  • sbyte,byte,short,ushort,int,uint,long,ulong,char,float,double,decimal或bool。

  • 任何枚举类型。

  • 任何指针类型。

  • 任何包含非托管类型字段的用户定义结构类型。

因此,您可以按以下方式定义结构以修复编译器错误:

public struct Results
{
    public int Id;
    public int Score;
    // Don't actually do this though.
    public unsafe char* Product;
}

这样,您可以指向数组的第一个元素。

但是,根据您编辑的问题,您需要在此处使用其他方法。

我有一个结果对象数组,我使用二进制序列化对它们进行了序列化。 现在,在程序的后期,我需要尽快对内存中的数据进行反序列化

通常,您将为此目的使用BinaryFormatter 如果那太慢,那么问题应该在于是否可以首先避免序列化。

===============>>#2 票数:1 已采纳

您不能指望它能起作用。

public struct Results
{
    public int Id;
    public int Score;
    public char[] Product;
}

char[]数组Product是托管类型。 您的代码尝试使用Results*类型Results* 那是一个指针类型。 文档指出,您可以声明指向以下任意项的指针:

  • sbyte,byte,short,ushort,int,uint,long,ulong,char,float,double,decimal或bool。
  • 任何枚举类型。
  • 任何指针类型。
  • 任何仅包含非托管类型字段的用户定义结构类型。

现在,您的结构显然与前三个项目符号都不匹配。 并且也不匹配最终的项目符号,因为数组是托管类型。

根据我的理解,我的结构的所有属性都是可漂白的属性。

是的,这是正确的,但不相关。 您需要该结构的成员不止是可蓝调的。


即使您的代码可以编译,您怎么会认为它可以工作? 考虑以下表达式:

*(Results*)packet

编译器如何将其转换为可创建新数组并复制正确数量的元素的东西? 因此很明显,编译器没有希望在这里做任何有用的事情,这当然就是该语言拒绝您的代码的原因。

我认为不安全的代码不会在这里为您提供帮助。 序列化数组时,必须先序列化长度,然后再序列化数组的内容。 要反序列化,您需要读取长度,创建具有该长度的新数组,然后读取内容。 不安全的代码无济于事。 静态定义类型的简单内存副本没有用,因为这意味着在编译时就知道了数组的长度。 它不是。


关于您的更新,您说:

我有一个使用二进制序列化序列化的Results对象数组。

为了反序列化,您需要了解二进制序列化详细布局的代码。 问题中的代码无法执行。

您可能还不了解的是,您不能期望复制任意长度的内存块,这些内存块的长度是可变的,并且只有在运行时才知道,而实际上没有人知道这些长度。 实际上,您希望能够在系统中没有任何内容知道要复制多少的情况下复制内存。

您尝试使用不安全的类型转换和内存副本进行反序列化的尝试无效。 如果不考虑序列化的二进制格式,就无法期望得到更详细的帮助。

  ask by ak1 translate from so

未解决问题?本站智能推荐: