首页 > 系统相关 >内存对齐

内存对齐

时间:2023-09-23 20:24:33浏览次数:34  
标签:字节 int double 编译器 内存 对齐

1、内存对齐是什么?

​ 计算机的内存就好像一个很大的数组,访问内存的时候,看似是可以从任何地址开始,但是实际上为了简化形成处理器和内存系统之间的接口设计,不同类型的数据会按照一定的规则在空间上排列,并不是按照顺序一个接着一个排放,这种排放方式就是内存对齐。

2、需要内存对齐的原因

​ 内存对齐能够提升处理器读取数据的效率,比如,假设一个处理器总是从内存中读取8个字节或者8个字节的倍数,如果储存double类型数据的地址不是8的倍数,那么可能需要读取两块8个字节的内存才能读取到这个double类型数据,若double类型数据的地址是8的倍数,则读取一次内存就能读取到这个double类型数据。

3、如何实现内存对齐

​ 在写程序的时候,优秀的编译器将会自动实现对齐的策略,一般的编译器比如VS、DEV C++等,默认都是8位字节对齐,就算不实现自动对齐,编译器也不会报错,只是会在效率上受影响,内存对齐可以看成一种使用空间效率换时间效率的方法。

​ 对齐的原则:任何K字节的基本对象的地址都必须是K的倍数,其基本类型的对齐K参数如下表所示:

K 类型
1 char
2 short
4 int,float
8 long,double,char*

​ 每种类型都按照上表的K来完成内存对齐。编译器在汇编代码中放入命令,来指令全局数据所需的对齐,例如,若要保证数据的起始地址是8的倍数,则可以包含以下命令:

.align 8

​ 在C语言中设置对齐的方式是,在开头声明如下代码:

#pragma pack(value)
//value为要设置的字节对齐数

​ 对于包含结构的代码,编译器会在字段的分配中插入间隙,从而保证每个结构元素都满足它的对齐要求,例如下面这个结构,假设编译器设置为4字节对齐:

struct a
{
	int i; //4个字节
	char c; //1个字节
	int j; //4个字节
};

int main()
{
	cout<<sizeof(a);
}

​ 理论上来说,这个结构体由两个int和一个char组成,其内存大小为9字节,然而输出为:

​ 理论上的内存分布,如图所示:

​ j的地址偏移为5,无法满足4字节的对齐要求,因此编译器会在字段c和j之间插入一个3字节的间隙:

​ 插入间隙之后,j的偏移量为8,便满足4字节的对齐要求,因此整个结构的大小也变为12字节。除了考虑结构体内的元素地址外,结构体的起始位置也就是图中的"0",不一定是真实内存中的0,可能是任意一段内存的起点,所以其结构体的起点,也就是struct a*类型的指针必须满足4字节对齐,这也就保证了结构体内的元素也是关于4字节对齐的。

标签:字节,int,double,编译器,内存,对齐
From: https://www.cnblogs.com/mjyrise/p/17724982.html

相关文章

  • JS深入学习笔记 - 第三章.变量作用域与内存
    1.原始值和引用值ECMScript变量包含两种不同类型是数据:原始值和引用值。原始值:最简单的数据。有6中原始值:Undefined、Null、Boolean、Number、String和Symbol。原始值是按值访问。引用值:由多个值构成的对象。三大引用类型:1.object2.Array类型3.Function类型。引用值是保存在......
  • 使用qemu来dump虚拟机的内存,然后用crash来分析
    场景如果虚拟机没有开启kdump,或者卡死了,那么可以进入qemu的monitor模式将虚机的内存保存到文件中,然后使用crash工具进行分析。示例启动虚拟机,然后按ctrl+ac进入monitor,查看帮助(qemu)helpdump-guest-memorydump-guest-memory[-p][-d][-z|-l|-s|-w]filename[beginl......
  • openGauss学习笔记-77 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT特性及
    openGauss学习笔记-77openGauss数据库管理-内存优化表MOT管理-内存表特性-MOT特性及价值本节介绍了openGauss内存优化表(Memory-OptimizedTable,MOT)的特性及价值。77MOT特性及价值MOT在高性能(查询和事务延迟)、高可扩展性(吞吐量和并发量)以及高资源利用率(某些程度上节约成本)方面......
  • 09_预处理 内存分区
    预处理内存分区全局变量:​ 不初始化默认为0​ 作用范围:当前源文件和其他源文件都有效​ 存储区域:全局区局部变量​ 不初始化值不确定静态局部变量​ 作用范围:所在{}​ 生命周期:整个进程​ 存储区域:全局区​ 不初始化默认为0静态全局变量​ 作用范围:......
  • 关于LXD容器出现OOM错误,以及添加内存条后容器无法启动的解决
    目前实验室的GPU服务器有4张3090显卡,但是只有32GB内存,频繁出现OOM(OutOfMemory)错误,因此博主通过添加大swap文件暂时缓解该问题,并采购内存条以解决该问题,同时解决添加内存条后lxc报错的问题。问题描述某次查看内核日志时,发现某容器出现了OOM(OutOfMemory)错误,有进程被强制kill,询......
  • 深入探讨Java面试中内存泄漏:如何识别、预防和解决
    引言在编写和维护Java应用程序时,内存泄漏是一个重要的问题,可能导致性能下降和不稳定性。本文将介绍内存泄漏的概念,为什么它在Java应用程序中如此重要,并明确本文的目标,即识别、预防和解决内存泄漏问题。内存泄漏的概念内存泄漏是指应用程序中分配的内存(通常是堆内存)在不再需要时......
  • JVM堆内存(heap)详解
    JAVA堆内存管理是影响性能主要因素之一。堆内存溢出是JAVA项目非常常见的故障,在解决该问题之前,必须先了解下JAVA堆内存是怎么工作的。先看下JAVA堆内存是如何划分的,如图:Java堆内存又溢出了!教你一招必杀技   JVM内存划分为堆内存和非堆内存,堆内存分为年轻代(YoungGeneration)、......
  • 7.1 实现进程内存块枚举
    在Windows操作系统中,每个进程的虚拟地址空间都被划分为若干内存块,每个内存块都具有一些属性,如内存大小、保护模式、类型等。这些属性可以通过VirtualQueryEx函数查询得到。该函数可用于查询进程虚拟地址空间中的内存信息的函数。它的作用类似于Windows操作系统中的TaskManager中......
  • java内存分配(堆,栈,方法区,常量池)图解
    大家都知道,java程序是运行在jvm(java虚拟机)上的,因此Java的内存分配是在JVM中进行的。那么在程序内存分配上面,大致分为:本地方法栈、程序计数器、虚拟机栈、java堆、方法区。这五类,本次主要讲解的是虚拟机栈、java堆和方法区中的内容。栈:存放基本数据类型的数据、引用数据类型的变量......
  • JAVA基础 —— 面向对象内存图
    JAVA基础——面向对象内存图......