C# 使用 StructLayoutAttribute 时 C# /C++ 内存空间分配与成员对齐问题
2024-08-28 00:50:56
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,问题解决 :)
最新文章
- rsync 通过 ssh 上传文件
- jboss的时区问题
- OC类方法和实例方法中的self区别
- BZOJ1722 [Usaco2006 Mar] Milk Team Select 产奶比赛
- hdu2717 Catch That Cow
- STL模板_map
- php+mysql 内联接 和 子查询
- Mac上关于shell使用Python3和C++11声明
- Linq学习系列-----1.2 一个简单方法的改进思考及不同的执行形式
- Python3实现ICMP远控后门(中)之“嗅探”黑科技
- 使用FaceNet 图像相识度对比
- js实现复选框的全选、全不选和反选
- 三十九、Linux 线程——线程的同步和互斥
- Confluence 6 嵌入的 H2 数据库
- 运行yarn的时候提示 node不是内部或外部命令
- BugPhobia终章篇章:学霸在线系统Beta阶段展示
- Calendar获取当前年份、月份、日期
- 【Android自动化】编写一个log模块,输出至控制台,供程序运行查看
- Linux - 用户操作
- 使用Axure RP原型设计实践06,登录验证