zoukankan      html  css  js  c++  java
  • C# 使用 StructLayoutAttribute 时 C# /C++ 内存空间分配与成员对齐问题

    1. 使用场景

    公共语言运行时控制数据字段的类或结构在托管内存中的物理布局。但是,如果想要将类型传递到非托管代码,需要使用 StructLayout 属性。

    2. 内存分配问题。

    如果不显示的设置内存对齐方式(通过StructLayout.Pack属性决定), C#默认是以4个字节(byte)为单位,会出现“多分配”内存的情况。 例如:

    Class Example
    {
       public byte b1;
       public char c2;
       public int i3;
    }
    

    默认情况下(StructLayout.Pack = 4),Framework编译器会为example对象分配8个字节(字段c2后面会补齐2个byte )。每个成员的索引和大小结果为:

         Size: 8

         b1 Offset: 0, lenght =1, 

         c2 Offset: 1, length = 1,

         i3 offset: 4, length = 4

    C++ 编译器的分配方式则为:

      Size: 6

         b1 Offset: 0, lenght =1, 

         c2 Offset: 1, length = 1,

         i3 offset: 2, length = 4

    由于内存分配的大小不一致,导致在传递对象marshal的时候回出现问题!!

    3. 解决方案。

    3.1 通过设置StructLayout.Pack的值来达到内存大小分配一致。

    例如在上面的例子中,设置StructLayout.Pack =2 或者 StructLayout.Pack =1. 但是这种方法可能会因为硬件约束导致性能或者其他问题。

    3.2 通过预留字段来“补齐”内存分配。

    这种做法在实际项目中使用较多,既保证了长度一致,也为以后扩展提供了一种容错的可能。 如果采取这种方式,重新定义如下:

    Class Example
    {
       public byte b1;
       public char c2;
       public int i3;
       
       [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
       public byte[] reserved;
    }
    

    至此,C#和C++分配的内存大小同为8,问题解决  :)  

     

  • 相关阅读:
    JS倒计时执行操作
    美化radio和checkbox样式
    ajax 多个表单值问题,表单序列化加其它表单值
    .net中的路径问题
    Response.Redirect 打开新窗口的两种方法
    GRIDVIEW FINDCONTROL的使用
    如何验证gridview控件的编辑行?如何获得gridview模板列<ItemTemplate/>中Label值?
    在Repeater的HeaderTemplate和FooterTemplate模板中寻找控件FindControl
    在GridView中使用FindControl(2)
    构造函数(C# 编程指南)
  • 原文地址:https://www.cnblogs.com/atuotuo/p/5019630.html
Copyright © 2011-2022 走看看