C基础--内存对齐问题(结构体对齐)

news2024/11/19 22:54:56

问题现象

  在调试一个软件功能时,发现一个结构体对齐的问题,以前没有太关注,现在把它总结出来。先看示例:

  • 结构体1:
typedef struct
{
	char magic[4];
	uint32_t crc32;
	uint32_t lenght;
	uint16_t ver;
	uint16_t IFrameCnt;
	uint32_t startTime;
	uint32_t startPts;
	uint32_t sliceTimeLen;
	uint32_t sliceLen;
	uint8_t res[16];
}RecSliceIndexHeader_t;

  RecSliceIndexHeader_t的大小为:sizeof(RecSliceIndexHeader_t) = 48

  • 结构体2:
typedef struct
{
	uint8_t codecType;
	uint8_t frameRate;
	uint8_t colorDepth;
	uint8_t frameInterval;
	int32_t quality;
	uint32_t bitRate;
	uint16_t width;
	uint16_t height;
	uint8_t isEncrypt;    
	uint8_t res[15];
}RecSliceVideoParam_t;

  通过sizeof得到结构体RecSliceVideoParam_t的大小为:sizeof(RecSliceVideoParam_t) = 32;

  • 结构体3:
typedef struct
{
	uint8_t codecType;
	uint8_t channel;
	uint32_t sampleRate;
	uint16_t bitsPerSample;
	uint8_t res[16];
}RecSliceAudioParam_t;

  通过sizeof得到结构体RecSliceAudioParam_t的大小为:sizeof(RecSliceAudioParam_t) = 28;

  • 结构体4:
typedef struct
{
	uint64_t time;
	uint32_t offset;
	uint32_t IFrameLen;
	uint8_t res[16];
}RecIFrameInfo_t;

  通过sizeof得到结构体RecIFrameInfo_t的大小为:sizeof(RecIFrameInfo_t) = 32;

  • 结构体5:
typedef struct
{
	RecSliceIndexHeader_t head;
	RecSliceVideoParam_t video;
	RecSliceAudioParam_t audio;
	RecIFrameInfo_t iFrame[1];
}RecSliceIndexInfo_t;

  通过sizeof得到结构体RecSliceIndexInfo_t的大小为:sizeof(RecSliceIndexInfo_t) = 144;
  ((unsigned long)(&((RecSliceIndexInfo_t*)0)->IFrameInfo[0])) = 112;
  sizeof(RecSliceAudioParam_t) +sizeof(RecSliceVideoParam_t)+sizeof(RecSliceIndexHeader_t) = 108

问题分析

问题1

  关于结构体3,它在内存中的实际对齐方式是:

typedef struct
{
	uint8_t codecType;
	uint8_t channel;
	uint32_t sampleRate;
	uint16_t bitsPerSample;
	uint8_t res[16];
}RecSliceAudioParam_t;

  它实际的对齐方式如下:

typedef struct
{
	uint8_t codecType;
	uint8_t channel;
	uint8_t res1[2];    // 编译器加对齐的字节
	uint32_t sampleRate;
	uint16_t bitsPerSample;
	uint8_t res1[2];    // 编译器加对齐的字节
	uint8_t res[16];
}RecSliceAudioParam_t;

  所以最终输出的值为:sizeof(RecSliceAudioParam_t) = 28;这个问题的关键是君正的字节对齐方式问题,在结构体内,它只要碰到4个字节的变量就会将结构体做4字节对齐。

问题2:

  关于结构体5,sizeof(RecSliceAudioParam_t)+sizeof(RecSliceVideoParam_t)+sizeof(RecSliceIndexHeader_t) 的值为108,我们发现RecIFrameInfo_t的成员uint64_t time的大小为8字节,因此导致108无法被8整除,在RecSliceIndexInfo_t 的IFrameInfo元素会填充4字节。因此成员IFrameInfo前面的元素整个大小为112字节。这个问题在组合结构体尤其需要关注。

改进措施

  在没有#pragma pack这个宏的声明下,结构体的对齐遵循下面四个原则:

  • 第一个成员的首地址为0。
  • 结构体的起始地址能够被其最宽的成员大小整除;
  • 结构体每个成员相对于起始地址的偏移能够被其自身大小整除,如果不能则在前一个成员后面补充字节。
  • 结构体总体大小能够被最宽的成员的大小整除,如不能则在后面补充字节。
    一般来说,不太建议使用#pragma pack这个宏,从找的资料看看,使用这个宏强制对齐在不同的平台可能会导致异常的BUG或者死机。

一般来说定义结构体遵循如下步骤,定义芯片平台对齐的字节数为PPB(以4字节对齐芯片平台举例,PPB=4):

  • 在单个结构体中,前面定义的成员遇到PPB大小的成员时,需要手动添加保留直接做对齐,或者调整成员的顺序,下面举例说明:
    在这里插入图片描述
    比如定义一个结构体:
      里面有x1、x2、x3、x4、x5、x6共6个元素,其中x1、x2、x3为char,x4为int类型即大小为4,和PPB相同。那么结构体定义的时候就要确保x1+x2+x3的大小是x4的整数倍(即4的整数倍),即需要在x1、x2、x3和x3之后再增加一个字节保证在x4之前对齐;(总的来说对应的是结构体的对齐遵循下面四个原则的第三点);
  • 在复合结构体中(结构体中包含结构体)
      上面问题遇到的问题,主要是复合结构遇到的问题,RecSliceIndexInfo_t的IFrameInfo是RecIFrameInfo_t结构体,这个RecIFrameInfo_t的time是8字节的,前面的所有长度为108,因此不够8整除,需要在前面三个成员加上4字节做对齐,即112字节。所以复合结构体中某个结构体有大于PPB的成员,需要仔细检查整个结构体的对齐问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/10980.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

多线程DPDK应用的内存优化

作者 Conor Walsh is a software engineering intern with the Architecture Team of Intel’s Network Platform Group (NPG), based in Intel Shannon (Ireland). 引言 高速包处理是一种资源密集型应用。一种解决方案是将包处理流水线(pipeline)分离到多线程以提高程序性能…

大一新生HTML期末作业,网页制作作业——海鲜餐饮网站登录页面(单页面)HTML+CSS+JavaScript

👨‍🎓静态网站的编写主要是用HTML DIVCSS JS等来完成页面的排版设计👩‍🎓,常用的网页设计软件有Dreamweaver、EditPlus、HBuilderX、VScode 、Webstorm、Animate等等,用的最多的还是DW,当然不同软件写出的…

STM32G0开发笔记-Platformio+libopencm3-FreeRTOS和FreeModbus库使用

title: STM32G0开发笔记-Platformiolibopencm3-FreeRTOS和FreeModbus库使用 tags: STM32MCUSTM32G070libopencm3MonkeyPiFreeRTOSModbus categories: STM32 date: 2022-9-11 19:52:05 [原文:makerinchina.cn] 使用Platformio平台的libopencm3开发框架来开发STM32…

docker -- 入门篇 (数据卷、自定义镜像、安装mysql redis)

1 数据卷 采用上一章节创建的centos镜像启动容器 doc01 docker run -it --name doc01 lhy/centos:1.00 2 数据卷容器 启动子容器doc02 实现继承doc01的关系 docker run -it --name doc02 --volumes-from doc01 lhy/centos:1.00 启动子容器doc03 实现继承doc01的关系 docker…

【计算机毕业设计】病人跟踪治疗信息管理系统源码

一、系统截图(需要演示视频可以私聊) 摘 要 病人跟踪治疗信息管理系统采用B/S模式,促进了病人跟踪治疗信息管理系统的安全、快捷、高效的发展。传统的管理模式还处于手工处理阶段,管理效率极低,随着病人的不断增多&a…

mac pro M1(ARM)安装:安装zookeeper可视化工具PrettyZoo、ZooKeeperAssistant

0. 引言 今天安装zookeeper的可视化工具遇到一些问题,将其记录下来,以供后续的同学参考,在mac软件安装上少走弯路。同时也让大家体会下这两款不同的zk可视化工具的差别 1. 安装PrettyZoo 1、下载 直接在github上选择版本下载: …

8 - 复习总结java中的继承与多态

1. 继承 1.1 为什么需要继承 先看一个例子: 比如猫和狗都是动物,都可以用一个类来描述。 使用java语言来描述: class Cat{String name;int age;float wight;public void bark(){System.out.println(name"汪汪汪叫");}public void eat(){S…

PyTorch使用快速梯度符号攻击(FGSM)实现对抗性样本生成(附源码和数据集MNIST手写数字)

需要源码和数据集请点赞关注收藏后评论区留言或者私信~~~ 一、威胁模型 对抗性机器学习,意思是在训练的模型中添加细微的扰动最后会导致模型性能的巨大差异,接下来我们通过一个图像分类器上的示例来进行讲解,具体的说,会使用第一…

Reactor 模型

文章目录1、网络编程关注的事件2、网络 IO 的职责2.1、IO 检测2.1.1、连接建立2.1.2、连接断开2.1.3、消息到达2.1.4、消息发送2.2、IO 操作2.2.1、连接建立2.2.2、连接断开2.2.3、连接到达2.2.4、消息发送3、Reactor 模式3.1、概念3.2、面试:Reactor 为什么使用非阻…

利用jenkins直接构件docker镜像并发布

一、本服务器构建 1.jenkins安装完成之后,打jenkins,选择新建任务,如: 2.进行〔源码管理〕配置,如: 3.构建执行配置,如: APP_NAMEtest-project APP_PORT8083 RUN_ENVprod cd /var/…

EtherCAT与RTEX驱动器轴回零的配置与实现

上节课程,正运动小助手给大家分享了运动控制器提供的回零模式配置与实现。本节课程主要介绍控制器实现EtherCAT与RTEX驱动器的回零及其配置。 01 总线驱动器回零模式 正运动控制器提供自己的回零模式,也支持使用EtherCAT总线驱动器提供的回零模式&…

学长教你学C-day9-C语言循环结构与选择结构

小刘最近在读《老子》,被道家“一生二,二生三”的哲学思想迷住了,他不禁想代码是谁生的呢?首先代码就是一堆字符,字符不是代码,就像“白马非马”,但是当字符按照一定的顺序组织起来时&#xff0…

《Python编程无师自通》读书笔记

不能越界访问函数内部定义的变量 global不能乱用 啥时候用元组 join连接 小点,但第一次见会觉得蛮有意思。 Hangman 10.1的案例蛮有意思的 一搜才发现是十分经典的文字游戏 过程式编程的缺点以及函数式编程和面向对象编程的解决方法 过程式编程的缺点 函数式编程…

Web学习笔记-中期项目(拳皇)

CONTENTS项目原理一、基础文件二、ac_game_object框架三、游戏地图与玩家模型的创建项目原理 游戏中一个物体运动的原理是浏览器每秒钟刷新60次,每次我们单独计算这个物体新的位置,然后把他刷新出来,这样最终人眼看起来就是移动的效果。 对…

YOLO系列概述(yolov1至yolov7)

YOLO系列概述(yolov1至yolov7) 参考: 睿智的目标检测53——Pytorch搭建YoloX目标检测平台YoloV7 yolo的发展历史 首先我们来看一下yolo系列的发展历史,yolo v1和yolox是anchor free的方法,yolov2,yolov3…

使用 Vue3 实现锚点组件

目录 1. 需求介绍 2. 实现过程 2.1 表单结构介绍 2.2 确定锚点组件接收的参数及使用方法 2.2.1 form-dom:需要被锚点组件控制的表单实例 2.2.2 active-anchor:默认激活的锚点 2.2.3 title-class:表单标题特有的类名 2.2.4 将 锚点组件…

5-FITC,5-FITC(isomer I),5-异硫氰酸荧光素,5-Flourescein iso-thiocyanate

产品名称:5-FITC,5-异硫氰酸荧光素 英文名称:5-Flourescein iso-thiocyanate 英文别名:5-FITC;5-Flourescein iso-thiocyanate;FITC Isomer I [5-FITC; fluorescein-5-isothiocyanate] CAS#:…

labview 串口通信 modbusRtu

在自动化或测试项目中,上位机软件需要和PLC及仪表通信,本文简单描述这个问题。 1.在程序框图中放置4个图标 (1)创建modbus 主站实例(按如下图标识①,在框图中放Create Master Instance.vi) 图1 放置四个图标 &…

C++ Reference: Standard C++ Library reference: Containers: deque: deque: resize

C官网参考链接&#xff1a;https://cplusplus.com/reference/deque/deque/resize/ 公有成员函数 <deque> std::deque::resize C98 void resize (size_type n, value_type val value_type()); C11 void resize (size_type n); void resize (size_type n, const value_t…

React组件复用

mixins&#xff08;已废弃&#xff09; https://react.docschina.org/blog/2016/07/13/mixins-considered-harmful.html mixin引入了隐式依赖关系 对于组件中的方法和数据的来源不明确&#xff0c;不容易维护 Mixins 导致名称冲突Mixins 导致滚雪球般的复杂性 render-props技术…