内存对齐

内存对齐

转载请注明,谢谢嗷~

引言

前几天笔者在用cpp进行BMP读入的时候,读入总是有问题

结果发现结构体写的并没有问题,二进制读入也没有问题

而是我的内存设定上出了问题,为了说明为什么让我们先看下图

看到这里,你感觉是不是人都傻了,int和char怎么会是8个字节嘞?

经过我一番深入研究,发现这原来是内存对齐产生的问题


强调

内存对齐可能在不同编译器直接存在差异

介绍

虽然所有变量是保存在特定地址的内存中,但是内部很多变量,如类,结构体中的,他们是按照内存对齐的方式储存的

什么叫对齐嘞?

通过填充0的方式,来使得存储内容的大小被扩大,成为特定值的某倍

原因有:

1)使得数据读取更加高效

2)不是所有的硬件平台都支持非对齐读入(特别是嵌入式系统中使用的低端处理器)

对齐原则pragma pack(x)

以下语句,设定了读取的最小单位x,以字节为单位

#pragma pack(x)

注意Windows环境下x默认为4字节

我们假设某个结构体中最大数据类型对应的字节数就是y

那么在这个结构体中,决定真正内存填充的基本单位MIN(x,y)

那么真正内存大小是MIN(x,y)乘以 填充数N

太抽象?举个栗子吧!

第一个例子,我们在上面的程序仅仅多添加了一句(光标所示位置

#pragma pack(1)

这就输出了我们心中的理想值

WHY?因为现在我们设置了最小读入单位为1字节,与结构体中最大内存的数据类型long long int比较,它依然是小者,所以当前填充的最小单位是1字节,这也就有了我们想要的结果

再看下面这个例子:

我们设置当前最小读入单位为2字节,同样比较于结构体中最大者,它依然小,所以当前内存填充字节数为2

结构体A好理解,那么B,C嘞?我们可以再看下图来直观感受一下

结构体是顺序储存,结构体B与C他们虽然都有两个字符型,但是由于内存填充最小单位的设定,最终使得他们的内存不一样


BMP读入的问题

现在再让我们看看BMP图像读入过程中,产生的问题吧

这是BMP(标准位图格式)文件头部分

注意这里设置是内存填充字节是默认的4字节

很明显,我们看到这个结构体,它里面即有unsigned int型,也有unsigned short型

那么问题就产生了,它读入就很容易读错,

并且两个short连着了一起,不表现出填充带来的异状

真正让这个文件出错的是

WORD bfType;

这个是短整型,再未加声明的情况下,莫名其妙被填充成4字节了,这也就使得该结构体成为了16字节,而非我们期望的14字节

这也就间接导致BMP的内容被我们过多地读入了,使得后面的内容前移

这会导致什么?像我这个例子,本来位图比较小的宽高被存成两个巨大无比的数,虽说这对24位后面每个像素的RGB读入影响不大,图像也处理成功了,但是内存溢出了并异常退出

那倘若下次宽高存的是别的值嘞?

posted @ 2020-05-19 19:20  et3_tsy  阅读(284)  评论(0编辑  收藏  举报