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,问题解决 :)
C# 使用 StructLayoutAttribute 时 C# /C++ 内存空间分配与成员对齐问题的更多相关文章
- Spark内核| 调度策略| SparkShuffle| 内存管理| 内存空间分配| 核心组件
1. 调度策略 TaskScheduler会先把DAGScheduler给过来的TaskSet封装成TaskSetManager扔到任务队列里,然后再从任务队列里按照一定的规则把它们取出来在Sched ...
- C++使用继承时子对象的内存布局
C++使用继承时子对象的内存布局 // */ // ]]> C++使用继承时子对象的内存布局 Table of Contents 1 示例程序 2 对象的内存布局 1 示例程序 class ...
- eclipse启动时虚拟机初始内存配置
eclipse启动时虚拟机初始内存配置: -Xms256M -Xmx512M -XX:PermSize=256m -XX:MaxPermSize=512m
- C++ 类T T t;构造时分配的内存在静态数据区 T t=new T()分配的内存在堆 这样说对吗
C++ 类T T t;构造时分配的内存在静态数据区 T t=new T()分配的内存在堆
- 使用C++做算法时,对内存的管理的办法
使用C++做算法时,对内存的管理的办法 最近老是在想C++的内存控制机制,查了一些资料所以有点想法,自己记录一下免得以后自己忘了. 1. 需求 在做线性代数的算法时,首要的就实现Matrix这个类.由 ...
- C#连接solr时提示 java内存异常 (jetty和tomcat哪个更High) java.lang.OutOfMemoryError
C#连接solr时提示 java内存异常 java.lang.OutOfMemoryError 时间:20180130 09:51:13.329,消息:异常消息<?xml version=& ...
- DenseNet算法详解——思路就是highway,DneseNet在训练时十分消耗内存
论文笔记:Densely Connected Convolutional Networks(DenseNet模型详解) 2017年09月28日 11:58:49 阅读数:1814 [ 转载自http: ...
- Linux OOM-killer 内存不足时kill高内存进程的策略
OOM_killer是Linux自我保护的方式,当内存不足时不至于出现太严重问题,有点壮士断腕的意味 在kernel 2.6,内存不足将唤醒oom_killer,挑出/proc/<pid> ...
- Linux OOM-killer(内存不足时kill高内存进程的策略)
OOM_killer是Linux自我保护的方式,当内存不足时不至于出现太严重问题,有点壮士断腕的意味 在kernel 2.6,内存不足将唤醒oom_killer,挑出/proc/<pid> ...
随机推荐
- 【C#】【Thread】Barrier任务并行
Barrier 是一个对象,它可以在并行操作中的所有任务都达到相应的关卡之前,阻止各个任务继续执行. 如果并行操作是分阶段执行的,并且每一阶段要求各任务之间进行同步,则可以使用该对象. --MSDN ...
- js下关于onmouseout、事件冒泡的问题经验小结
问题是这样的:一个div元素要触发onmouseout事件,同时这个div内部还有子元素,于是当鼠标移动到该div的子元素上时,onmouseout事件也被触发了.在要做浮动层效果的时候会经常遇到这个 ...
- BAD APPLE C++控制台程序
使用C++语言编写,如果想改成C语言,手动以GetProcAddress的方式来调用相关函数即可. #include <windows.h> #include <mmsystem.h ...
- WCF学习笔记一
Windows Communication Foundation(WCF)是由微软开发的一系列支持数据通信的应用程序框架,可以翻译为Windows 通讯开发平台. 整合了原有的windows通讯的 . ...
- web框架 之 Tornado
初识 Tornado : tornado web server 是使用python编写出来的一个轻量级.高可伸缩性和非阻塞IO的Web服务器软件,其特点是采用epoll非阻塞IO,相应快速,可处理数千 ...
- 如何判断自己的VPS是那种虚拟技术实现的
我们知道VPS的虚拟技术有许多种,如Openvz.Xen.VMware vSphere.Hyper-V.KVM及Xen的HVM与PV等.在Xen中pv是半虚拟化,hvm是全虚拟化,pv只能用于linu ...
- signalr遇到的问题汇总
1.signalr不会触发 hub类的连接事件和断开连接事件 解决:当时因为我引用的是最新的类库 .当时想到的是类库版本问题.就将他换成官方demo一模一样 发现还是不行..然后用官方demo的客户端 ...
- Jstat PID not found
解决步骤 删除/tmp/hsperfdata_{USER}文件夹,如果是root用户登录,即为/tmp/hsperfdata_root 通过chown.chmod命令保证执行jstat用户必定拥有对/ ...
- 使用Swift打造动态库SDK和DemoAPP时所遇到的(Xcode7.3)
使用Swift开发SDK的优点是,生成的SDK对于Obj-C或是Swift调用都不需要自己去建桥接文件,因为Swift的SDK打包时默认已经自动生成供OC调用的.h文件.OC调用时直接import,s ...
- 配置samba
安装samba服务器之后,很方便的实现Windows和Linux进行通信. 安装步骤:1.在Ubuntu系统下面安装samba服务: nii@ww:~$ sudo apt-get install sa ...