• 内存对齐


    内存对齐

    转载请注明,谢谢嗷~

    引言

    前几天笔者在用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读入影响不大,图像也处理成功了,但是内存溢出了并异常退出

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

  • 相关阅读:
    plsql Developer11的工具栏没有了如何找回来
    postman发送HTTP请求自动生成MD5/SHA1签名
    Redis的安装+哨兵模式+集群
    SpringBoot笔记 --- @JsonFormat和@DateTimeFormat的作用
    HBase异常 -- hbase list报错 ERROR: org.apache.hadoop.hbase.PleaseHoldException: Master is initializing
    Windows使用进阶
    SpringBoot笔记 -- @RequestParam、@RequestBody、@PathVariable、@param
    SpringBoot笔记 -- 注解
    Mybatis笔记 -- 批量操作(查询、插入、更新、删除)
    Git异常 -- 汇总
  • 原文地址:https://www.cnblogs.com/et3-tsy/p/12918932.html
Copyright © 2020-2023  润新知