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++ 内存空间分配与成员对齐问题的更多相关文章

  1. Spark内核| 调度策略| SparkShuffle| 内存管理| 内存空间分配| 核心组件

    1. 调度策略 TaskScheduler会先把DAGScheduler给过来的TaskSet封装成TaskSetManager扔到任务队列里,然后再从任务队列里按照一定的规则把它们取出来在Sched ...

  2. C++使用继承时子对象的内存布局

    C++使用继承时子对象的内存布局 // */ // ]]>   C++使用继承时子对象的内存布局 Table of Contents 1 示例程序 2 对象的内存布局 1 示例程序 class ...

  3. eclipse启动时虚拟机初始内存配置

    eclipse启动时虚拟机初始内存配置: -Xms256M -Xmx512M -XX:PermSize=256m -XX:MaxPermSize=512m

  4. C++ 类T T t;构造时分配的内存在静态数据区 T t=new T()分配的内存在堆 这样说对吗

    C++  类T   T t;构造时分配的内存在静态数据区   T t=new T()分配的内存在堆

  5. 使用C++做算法时,对内存的管理的办法

    使用C++做算法时,对内存的管理的办法 最近老是在想C++的内存控制机制,查了一些资料所以有点想法,自己记录一下免得以后自己忘了. 1. 需求 在做线性代数的算法时,首要的就实现Matrix这个类.由 ...

  6. C#连接solr时提示 java内存异常 (jetty和tomcat哪个更High) java.lang.OutOfMemoryError

    C#连接solr时提示 java内存异常   java.lang.OutOfMemoryError 时间:20180130 09:51:13.329,消息:异常消息<?xml version=& ...

  7. DenseNet算法详解——思路就是highway,DneseNet在训练时十分消耗内存

    论文笔记:Densely Connected Convolutional Networks(DenseNet模型详解) 2017年09月28日 11:58:49 阅读数:1814 [ 转载自http: ...

  8. Linux OOM-killer 内存不足时kill高内存进程的策略

    OOM_killer是Linux自我保护的方式,当内存不足时不至于出现太严重问题,有点壮士断腕的意味 在kernel 2.6,内存不足将唤醒oom_killer,挑出/proc/<pid> ...

  9. Linux OOM-killer(内存不足时kill高内存进程的策略)

    OOM_killer是Linux自我保护的方式,当内存不足时不至于出现太严重问题,有点壮士断腕的意味 在kernel 2.6,内存不足将唤醒oom_killer,挑出/proc/<pid> ...

随机推荐

  1. MVC4 自定义错误页面(转)

    一.概述 MVC4框架自带了定义错误页,该页面位于Shared/Error,该页面能够显示系统未能捕获的异常,如何才能使用该页面: 二.使用步骤: 1.配置WebConfig文件,在System.We ...

  2. 微信小程序购物商城系统开发系列-目录结构

    上一篇我们简单介绍了一下微信小程序的IDE(微信小程序购物商城系统开发系列-工具篇),相信大家都已经蠢蠢欲试建立一个自己的小程序,去完成一个独立的商城网站. 先别着急我们一步步来,先尝试下写一个自己的 ...

  3. c语言游戏推箱子

    前两天做了推箱子小游戏,看似简单的一个小游戏背后却 有巨大的秘密,这秘密就是一大堆逻辑. 自从学习了函数过后,的确是解决了很多问题,而且调用很方便,尽管我现在都不是很会调用. 写完一个函数,准备测试一 ...

  4. jquery修改带!important的css样式

    由于需求的需要,今天在用jquery修改一个弹出框的样式的时候,由于有一个按钮有padding-left:12px;导致内间距空出来的这一块颜色用普通的方式无法改变. 普通的jquery修改css的方 ...

  5. 我也来写:数据库访问类DBHelper

    一.前言 相信许多人都百度过:“.net 数据库访问类”.然后就出来一大堆SqlHelper.我也用过这些SqlHelper,也自己写过,一堆静态方法,开始使用起来感觉很不错,它们也确实在很多时候可以 ...

  6. ajax(通过jQuery实现)

    使用jQuery实现ajax相对来说方便一点,看w3cschool有几种实现的方法,我就总结一下自己以后会用到的几种方法 $.ajax方法: $.ajax方法里面有很多个参数可以使用,但我这里就写自己 ...

  7. iOS小知识点(UI部分)

    1. 父视图通过Tag来找到UIView UIView *targetView = [superView viewWithTag:10];//只在当前视图以及subviews中找,不能再孙子中找. 2 ...

  8. AOJ DSL_2_C Range Search (kD Tree)

    Range Search (kD Tree) The range search problem consists of a set of attributed records S to determi ...

  9. linux下压缩,解压缩的方法

    linux zip命令 zip -r myfile.zip ./* 将当前目录下的所有文件和文件夹全部压缩成myfile.zip文件,-r表示递归压缩子目录下所有文件. 2.unzip unzip - ...

  10. POJ 2342 Anniversary party(树形dp)

    Anniversary party Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7230   Accepted: 4162 ...