怎么调试内存溢出的c++代码_【C/C++】内存对齐 到底怎么回事?

fe8c331809a8595b2131ad8a69254788.png

1 明确几个概念

代码分区:在使用C/C++编程时,我们定义的变量存在于内存中,而内存在C语言的角度上可以分为五大区。局部变量在栈区,静态/全局变量在全局区,动态申请的变量存在于堆区,const修饰的变量/字符常量存在于只读区。无论是什么样的变量,终究在内存中。

CPU取指,译码,执行:存在于内存中的目的是为了CPU通过总线的进行寻址,取指令,译码,执行取数据,内存与寄存器交互,然后CPU运算,再输出数据至内存。这个过程反复的,高速的执行。

CPU位数:在计算机中,最小的存储单元为字节(Byte),理论上任意地址(比如0x20000002,0x20000003,0x2000011...)都可以通过总线进行访问(CPU寻址),而每次寻址后,传输的数据大小跟CPU位数相关,常见的CPU位数有8位,16位,32位,64位。位数越高,单次操作执行的数据量越大,性能也就越强。

OS位数:操作系统一般与CPU位数相匹配,32位CPU可以寻址4GB内存空间,可以运行32位的OS。同样,64位的CPU可以运行32位的OS,也可以运行64位的OS。

Compiler:虽然编译器都是在翻译/编译代码,进行预处理(宏展开,头文件展开),编译(语法检查等),汇编(翻译为机器码),链接(重定位等)这四部分的工作。但是不同的编译器的内部默认设置以及用法会有所差异,常用的有GCC,VS,Clang,MinGW等。

2 指定平台

不谈平台,只谈编码,就是在耍流氓。---哈哈哈

这里的平台指的是三大件:CPU + OS + Compiler

本文中实验的平台是:Intel i7 + ubuntu16.04 + gcc5.4

有了上面的基本概念了解,就可以进行分析了。

3 为什么要内存对齐?

原因有两点:

CPU每次寻址都是要消费时间的,如果一次取不完数据就要取多次。比如int类型的变量a占4Byte,假设在内存中没有对齐(所谓对齐,指的是内存中数据的首地址是CPU单次获取数据大小的整数倍),且存放在0x00000003 - 0x00000006处(0x00000003不是4的整数倍)。那么每次取4字节(32位宽总线)的CPU第一次取到[0x00000000 - 0x00000003],只得到变量a的1/4数据,进而需要进行第二次取数[0x00000004 - 0x00000007],为了得到int类型的一个变量,却需要两次访问内存,并且还需要拼接处理,性能较低,这是其一

有些CPU(ARM架构的)在内存非对齐的情况下,执行二进制代码会崩溃,因为不是所有的硬件平台都能访问任意地址上的任意数据的。倘若代码移植到其他不支持的平台上,不具有可移植性,这是其二。

若在编译时,将分配的内存进行对齐,单次访问内存就可以获取数据,并且具有平台可移植性。

那谁来把我们编写的结构体,类中的成员变量进行对齐呢?

当然是编译器(Compiler)。那对齐的规则又是如何呢?

4 内存对齐规则

编译器提供手动指定对齐值的关键字 #pragma pack(N),可以手动设置对齐的字节数,比如#pragma pack(1),#pragma pack(4)等。这里即为N。

若没有手动指定,那么编译器就会默认将成员变量中最大的类型字节数设置为对齐值:m

1 整体对齐值:

首先计算对齐单位 n = min{N,m},然后整体对齐后的字节数应该为n的倍数,不够的在最后面填补占位。

2 成员对齐值:

首个成员的偏置地址(offset) = 0。

假定该成员的类型占字节数 j,那么本成员的偏移地址(offset):min{n, j}的整数倍。

5 代码实测

#include 

以上注释为理论分析

现在编译,并执行输出看看是否sizeof = 24。

be7b290b89dc08886ed20ac77f8ccf51.png

这里使用的GCC中的g++进行编译。

也可以用gcc,不过要链接c++的标准库(-lstdc++),否则会链接失败。

df119e679c5727e9e22de9d12a0bdbfd.png

这里实验结果与理论分析的一致。

另外:如果手动设置#pragma pack(4),后效果如何呢?

#pragma pack(4)

查看结果是否为sizeof = 20呢?

a24a10ce0f18152990bce70c6828c4b5.png

显然,是和分析的一致。

6 总结

这里以C++的类为例,进行内存对齐分析。关于C++的内存布局,以及含有virtual函数的类,实际上还会更复杂。简单的就如最基本的类,这和C中的struct是非常类似的。

掌握C++中类的内存对齐,有助于进一步理解C++对象模型。

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

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

相关文章

js粘贴板为什么获取不到图片信息_图床+typora,告别markdown中关于图片的困惑

在上一篇文章中向大家介紹了几款软件,这篇文章主要分享一下markdown编辑器typora软件如何使用图床,快速的将图片加载到markdown文档中。图床:指存储图片的服务器,将图片上传到服务器上,转换成链接为什么使用图床&#…

计算机二级mysql是什么_计算机二级mysql考什么内容?

计算机二级mysql考什么内容?一、基本概念与方法1、数据库基础知识(1)数据库相关的基本概念(2)数据库系统的特点与结构(3)数据模型2、关系数据库、关系模型3、数据库设计基础(1)数据库设计的步骤(2)关系数据库设计的方法4、MySQL概述(1)MySQL系统特性与工…

eclipse软件有时会退出弹出一串错误弹框_修复iPhone上的iOS 13软件更新失败错误...

如果由于“软件更新失败:下载iOS 13时发生错误”错误而无法安装刚刚发布的用于检查新的暗模式功能的iOS 13更新,那么我可以理解这种挫败感。但幸运的是,有些解决方案可以尝试修复某些用户报告的iOS 13软件更新失败错误。解决iPhone 13软件失败…

mysql第四章分页显示查询出租房屋信息_MYSQL必知必会读书笔记第四章之检索数据...

MySQL是一种开放源代码的关系型数据库管理系统(RDBMS),MySQL数据库系统使用最常用的数据库管理语言--结构化查询语言(SQL)进行数据库管理。使用Select语句返回的数据,可能会发现显示的数据会与其他的地方顺序不同。出现这种情况很正常。如果没有明确排序…

vep文件如何转换mp4_如何将DVD的vob视频格式转换成mp4格式

首先简述一下,VOB是DVD Video OBject的缩写,vob文件用来保存所有MPEG-2格式的音频和视频数据,这些数据不仅包含影片本身,而且还有供菜单和按钮用的画面以及多种字幕的子画面流。如何把视频vob格式转换成任意格式视频文件呢&#x…

esp8266接收到的数据如何存放到数组中_Java中HashMap的实现原理

最近面试中被问及Java中HashMap的原理,瞬间无言以对,因此痛定思痛觉得研究一番。一、Java中的hashCode和equals1、关于hashCodehashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用来在散列存储…

python测试用例管理_Python测试框架Pytest的常用插件测试报告

原标题:Python测试框架Pytest的常用插件测试报告一、pytest-html 生成 html 测试报告 要求:Python 3.6 安装:pip install pytest-html 文档:https://github.com/pytest-dev/pytest-html、https://www.cnblogs.com/linuxchao/p/lin…

python symbol函数展开_QGIS表达式中的函数

编程语言中的函数,与数学函数的定义大不相同。在计算机领域,函数是指一段可以直接被另一段程序或代码引用的程序或代码,也叫做子程序(subroutine)、过程(procedure)、方法(method)。函数在QGIS表达式构建过程中起到重要作用,表达式…

layui 金额数据千分位_IG神秘打野韩服数据,盲僧数据或暗示英雄池问题

在LPL春季赛结束,而夏季赛还未开始的这段时间,是LPL各大战队能够利用的宝贵时间。为了备战S10,有一些队伍确实需要引援。而在这次转会期期间,率先出现转会传闻的是IG战队。据传IG打野Leyan有离队的可能,同时IG也在积极…

python设计模式pdf_精通Python设计模式 高清晰PDF+源码

精通Python设计模式讲述了16种基本设计模式,轻松解决软件设计常见问题;借力高效的Python语言,用现实例子展示各模式关键特性。 本书用实际生活中的例子带你了解常用的设计模式,介绍了诸多有关编写Python风格代码的底层细节和概念&…

datanode无法启动_Hadoop DataNode启动和初始化过程

简介我们先看DataNode的doc文档的介绍,DataNode是一个类,用于存储一组块,用于DFS部署。单个部署可以有一个或多个DataNode。每个DataNode通信定期与单个NameNode进行通信。它还可以与客户端和其他的DataNodes通信。DataNode存储一系列命名的块…

挖掘机燃料_2020广东挖掘机工程机械出租公司合作共赢

如今的挖掘机具有比以往更多的内置安全功能,但这并不意味着只有任何人都可以爬上驾驶室并安全操作。1、仔细检查地面区域使用挖掘机时,诸如岩石、建筑材料和树桩之类的物品会损害安全性。在开始操作机器之前,请确保已将其从该区域中清理。此外…

mysql对所有列的数据进行修改6_MySQL的SQL语句 - 数据定义语句(6)- ALTER TABLE 语句 (3)...

添加和删除列使用ADD向表中添加新列,使用DROP删除现有列。DROP col_name是对标准SQL的MySQL扩展。若要在表行的特定位置添加列,请使用FIRST col_name 或者 AFTER col_name。默认情况是添加到最后。如果表只包含一列,则不能删除该列。如果您想…

ant构建项目迁移到gradle_Gradle构建工具

构建工具的作用:依赖管理;测试、打包、发布;机器能干的活,绝不自己动手。主流构建工具:(1)Ant:编译、测试、打包;(2)Maven:依赖管理、发布;(3)Gradle:Groovy&…

mysql导入数据库某张表_MSSQLServer2005 导出导入数据库中某张表的数据

备注:在工作中我们经常会遇到,将数据库中某张数据表中的内容或数据导出来;今天我们就介绍怎样快速有效的进行数据导出,导入。使用的数据库版本为:mssqlserver2005。首先进行登录mssqlserver2005 ,如下图所示…

pyecharts运行了但是没有图_新版pyecharts,Python可视化so easy and powerful !

作者:chenjiandongx一个执迷于写 bug 的程序员pyecharts V1.0.0 版本正式发布啦!Whats New in pyecharts V1pyecharts 经过了半年的沉寂后,终于发布了新版本啦!新版本号将从 v1.0.0 开始,这是一个全新的,向…

python 整除及余数_python除法余数

广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 常量常量就是不变的变量,在python中,通常用大写的变量名表示常量,这一点…

flatmap用法_短说:map和flatmap

PS:本文阅读->理解->GET大概2-5分钟.也许你天天见到,但是一直没理解,占用你少量的时间,相信简单的东西,只需要你付出一点点时间.map和flatmap是Java8中stream的用法.>>>>>>map把数组流中的每一个值,使用所提供的函数执行一遍,一…

git 回退到某个commit_it lesson2 版本回退

回顾上次的知识:1,首先git init 初始化文件的状态,使用git管理文件。2,git add xxx 告诉git把xxx文件添加到仓库3,git commit -m ‘xxxx’告诉git把文件提交到仓库 并对提交的内容作解释(‘xxxx’&#xff…

python数据处理模块pandas_13. Python|模块总结:Pandas(数据处理)|【老W笔记】...

一、基本操作0. 导入模块import pandas as pd1. 新建DataFrame下面的例子中,我们新建一个有3条记录2列属性的表格。3 条记录分别是Tom,Bob,Alice的个人信息,2列属性分别是name和age。新建属性列的语法形如df[XX] List,…