进程的虚拟地址空间

news2025/7/21 4:28:28

每个程序运行起来后,都拥有一个自己的虚拟地址空间(注意是虚拟的,不是实际存在的),这个虚拟地址空间的大小由计算机的硬件平台

关于虚拟的概念,当时IBM给出了一种说法很形象生动:
它存在,你能看得见,它是物理的
它存在,你看不见,它是透明的
它不存在,你却看得见,它是虚拟的
它不存在,你也看不见,它被删除了!

决定,具体地说是由CPU位数决定的。硬件决定了地址空间的最大理论上限,即硬件的寻址空间大小,比如32位的硬件平台决定了虚拟地址空间的地址为0到2^32 - 1,即0x00000000~0xFFFFFFFF,也就是我们常说的4GB虚拟空间大小,也就是它只有4GB的寻址能力。
现在让我们来看一下x86体系下32位Linux环境中进程虚拟地址空间:
在这里插入图片描述
了解了地址空间,我们就能对程序有更深入的理解。
这里介绍一下每一节中存放的内容:

.text:已编译程序的机器代码
.rodata:只读数据,比如printf语句中的格式串和开关语句的跳转表
.data:已初始化的全局和静态变量。注意局部变量在运行时被保存在栈中,既不出现在.data节中,也不出现在.bss节中
.bss:未初始化的全局和静态变量,以及所有被初始化为0的全局或静态变量。这个节不占据实际的空间,它仅仅是一个占位符。
区分已初始化和未初始化变量是为了空间效率,未初始化变量不需要占据任何实际的磁盘空间。运行时,在内存中分配这些变量,初始值为0

一种记住.data和.bss节之间区别的简单方法是把“bss”看成是“更好地节省空间(Better Save Space)的缩写”(.bss中的值都为0)

举个例子:

int gdata1 = 10;
int gdata2 = 0;
int gdata3;

static int gdata4 = 11;
static int gdata5 = 0;
static int gdata6;

int main()
{
	int a = 12;
	int b = 0;
	int c;

	static int e = 13;
	static int f = 0;
	static int g;

    cout << c << g << endl;
    //c不为零,g为零
    
	system("pause");
	return 0;
}

根据上面的规则,各个变量存放在哪块内存呢?

gdata1和gdata4初始化且不为0,存放在.data段
gdata2、gdata3、gdata5、gdata6未初始化或初始化为0,存放在.bss段

a,b,c不会产生符号,编译成指令,指令存放在.text段
mov dword ptr[a], 0ch

e初始化了,且不为0,存放在.data段
f和g初始化为0,或未初始化,存放在.bss段

注意一点,虽然a变量是局部变量,存放在栈上,
但有一点需要明确a = 12编译后生成指令,存放在.text段,只是在运行时,在栈上开辟空间

知道了每节存放的内容,或许就能更好的理解程序
比如,为什么有时会发生栈溢出(stack overflow)?
栈向低地址增长,栈空间是有限的,当递归函数递归太深就会爆栈(关于函数调用是如何开辟栈空间的之后再谈)

为什么程序常常会出现”段错误(segment fault)“或”非法操作,该内存地址不能read/write“的错误信息?
这往往是因为指针指向一个不允许读或写的内存地址,而程序却试图利用指针来读写该地址的时候,就会出现这个错误。在Linux或Windows的内存布局中,有些地址是始终不能读写的,例如0地址。

还有这样的程序为什么报错?

char *p = "hello, world";
*p = 'a';

因为”hello, world“作为字符串常量存放在只读数据段中,修改只读数据段当然不可以。
等等,当我们之后遇到此类问题时,都可以想想它在内存中是怎么存储的,从而明白为什么出错。
一些小点:
1.栈通常只有数兆字节的大小,而堆一般比栈大很多可以有几十至数百兆字节的容量。程序使用mallocnew分配内存时得到的内存都来自堆里。
2.Windows在默认情况下会将高地址的2GB空间分配给内核(也可配置为1GB),而Linux默认情况下将高地址的1GB空间分配给内核。

思考,数据什么时候可以放在栈上,什么时候又需要放在堆上呢?
栈是程序运行的基础,函数调用的过程中,通过移动栈指针开辟足够的空间,用来存放函数使用到的局部变量,以及函数中使用到的通用寄存器的副本(以便在函数调用结束后,通过副本可以恢复到函数调用之前)。编译器编译并优化代码时,一个函数就是一个最小的编译单元,所以在编译阶段,编译器就得知道要存放哪些局部变量和寄存器,以便预留空间。所以编译期可以确定大小的”放在“(预留,运行时开辟)栈上,对于无法确定大小或大小可以改变的数据,最好放在堆上。除了动态大小的需要放在堆上,动态生命周期的内存也需要分配到堆上。因为栈上的内存在函数调用结束后,会被回收(实则是改变栈指针,数据并不会被清空),对于栈上内存的生命周期是不受开发人员控制的,局限在当前调用栈中。而堆上开辟的内存需要显式释放,因此堆上的内存就有更加灵活的生命周期,可以在不同的调用栈之间共享数据。总结下来,栈上的数据是静态的,大小固定,生命周期固定,而堆上的数据是动态的,大小不固定,生命周期不固定。

以上便是进程的虚拟地址空间的介绍,这里只关注了几个常用的节,关于这部分知识点很多,之后继续总结。
正文结束,这里通过一个小例子来测试指针在不同平台下、不同类型下的大小:
一般来说,C语言指针大小的位数与虚拟空间的位数相同,如32位平台下的指针为4字节,64位平台下的指针为8字节。

这里有一个经典的面试题,就是问指针大小,比如32位操作系统下,int *p和char *p,p的大小是多大?
都是4字节,因为p是指针类型,p存放的是内存地址,与类型无关。

32位环境下:
在这里插入图片描述
64位环境下:
在这里插入图片描述
参考资料:
[1] 龚奕利,贺莲译.深入理解计算机系统[M].北京:机械工业出版社,2016.
[2] 俞甲子,石凡,潘爱民著.程序员的自我修养:链接、装载与库[M].北京:电子工业出版社,2009.4

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

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

相关文章

XSS-labs靶场实战(三)——第7-8关

今天继续给大家介绍渗透测试相关知识&#xff0c;本文主要内容是XSS-labs靶场实战第7-8关。 免责声明&#xff1a; 本文所介绍的内容仅做学习交流使用&#xff0c;严禁利用文中技术进行非法行为&#xff0c;否则造成一切严重后果自负&#xff01; 再次强调&#xff1a;严禁对未…

PyQt5_股票策略校验工具_升级版

相对 PyQt5_股票策略校验工具 博文&#xff0c;图形展示方面增加多行图展示&#xff0c;原本只有K线图&#xff0c;升级版工具可以动态添加多行指标图 股票策略有效与否的确认&#xff0c;需要在不同股票&#xff0c;不同时间段&#xff0c;运行对比&#xff0c;确认在哪些条件…

图文轻松说透 K8S Pod 各种驱逐场景

图文轻松说透 K8S Pod 各种驱逐场景 Kubernetes Pod 被驱逐是什么意思&#xff1f; 它们被终止&#xff0c;通常是没有足够资源的结果。但是为什么会这样呢&#xff1f; 驱逐是指派给节点的Pod 被终止的过程。Kubernetes 中最常见的情况之一是Preemption&#xff0c;为了在资…

基于PHP+MySQL健身俱乐部系统的设计与实现

随着时代的发展和人们对生活的热爱,健身已经成为人们工作之余的一种热爱,相对应的各种健身俱乐部也如雨后春笋般出现,处于宣传的目的各类健身俱乐部网站也不断的出现,处于对健身俱乐部的宣传作用,我们通过PHP语言和MYSQL数据库开发了健身俱乐部系统 PHP&#xff1a;MySQL健身俱…

笔试强训第29天(有假币+求正数数组的最小不可组成和)

单选 A选项&#xff1a;当内存访问越界的时候&#xff0c;线程会收到信号&#xff0c;进而进行信号处理。调用信号处理函数。 B选项&#xff1a;ACM时间。 A&#xff1a;最后访问时间&#xff0c;文件被读取而更新的时间 C&#xff1a;状态修改时间&#xff0c;文件的属性或者权…

pymsql模块+事务+mysql 注入+数据库备份和恢复

import pymysqlconn pymysql.connect(host127.0.0.1, userroot, password123456, databasehomework) # cur conn.cursor(cursorpymysql.cursors.DictCursor)#查询返回字典 cur conn.cursor() # cursor游标&#xff0c;默认返回元组 try:cur.execute(select * from students…

前端加密与解密

插件加密 MD5加密&#xff08;不可逆&#xff09; MD5加密是不可逆的&#xff0c;相当于是插件加密&#xff0c;当然你也可以把他的方法抄过来自己实现。 MD5.js是通过前台js加密的方式对用户信息&#xff0c;密码等私密信息进行加密处理的工具&#xff0c;前端用的比较多。…

【毕业设计】深度学习手势识别检测系统 - python

文章目录1 前言2 项目背景3 任务描述4 环境搭配5 项目实现5.1 准备数据5.2 构建网络5.3 开始训练5.4 模型评估6 识别效果7 最后1 前言 &#x1f525; Hi&#xff0c;大家好&#xff0c;这里是丹成学长的毕设系列文章&#xff01; &#x1f525; 对毕设有任何疑问都可以问学长…

【ASE+python学习】批量实现将含有空位的结构进行氢饱和(实际就是在某个位置添加氢原子)

批量实现将含有空位的结构进行氢饱和任务大纲任务思路氢原子相对位置计算代码实现-单个结构加氢导入所需库/包计算氢原子坐标给结构加氢运行结果代码实现-批量结构加氢导入相关库/包遍历文件夹内所有结构&#xff0c;并逐次给结构加氢批量实现的逻辑与结果在搬砖过程中&#xf…

【教学类-15-01】20221115《学号(姓名)描字帖-A4横版-竖切》(中班)

效果展示 浅蓝色打印纸&#xff08;灰色字体&#xff09; 背景需求&#xff1a; 在中3班的Python学具实验中&#xff0c;发现至少有3位幼儿明确表示自己不会写学号&#xff0c;还有3位幼儿书写的学号是镜像字&#xff08;两个数字位置互换、两个数字都左右镜像、2和5上下镜像等…

【树莓派不吃灰】命令篇⑤ ps -ef | grep xxx | grep -v grep | wc -l 命令

目录1. 简介2. grep -v grep 命令作用2.1 ps -ef | grep python32.2 grep -v grep❤️ 博客主页 单片机菜鸟哥&#xff0c;一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2022-11-18 ❤️❤️ 本篇更新记录 2022-11-18 ❤️&#x1f389; 欢迎关注 &#x1f50e;点赞 &am…

让 Serverless 更普惠,阿里云函数计算 FC 宣布全面降价,最大幅度达 37.5%

背景 11 月 5 日&#xff0c;2022 杭州 云栖大会上&#xff0c;阿里云宣布函数计算 FC 开启全面降价&#xff0c;vCPU 单价降幅 11% &#xff0c;其他的各个独立计费项最高降幅达 37.5% 。 本次云栖大会上&#xff0c;阿里云智能总裁张建锋表示&#xff0c;以云为核心的新型…

动态分区算法(头歌实验)第1关:首次适应算法。第2关:最佳适应算法。

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 题目&#xff1a; 第1关&#xff1a;首次适应算法 任务描述 假设初始状态下可用的内存空间为55MB&#xff0c;并有如下的请求序列&#xff1a; 作业1申请15MB 作业2申请30M…

Yolov5+图像分割+百度AI接口——车牌实时检测识别系统

Hallo&#xff0c;各位小伙伴大家好呀&#xff01;这两天一直在肝项目&#xff0c;都是关于计算机视觉方面的&#xff0c;所以这两天一直也没有更新&#xff08;真的不是我懒&#xff09;&#xff01;在这个过程中我对Yolov5有了更深刻的理解&#xff0c;在原有的Yolov5框架上增…

14.4、SpringWebFlux-2

14.4、SpringWebFlux-2 14.4.3、SpringWebFlux执行流程和核心 API SpringWebFlux 基于 Reactor&#xff0c;默认容器是 Netty&#xff0c;Netty 是高性能的 NIO 框架&#xff0c;异步非阻塞&#xff08;AIO&#xff0c;是 NIO 的升级&#xff09;的框架 14.4.3.1、执行流程 …

jrtplib开源库系列之三:jrtplib发送接收数据流程

说明 前面2篇文章主要说明了如何安装jrtplib库&#xff0c;以及对example1进行了说明&#xff0c;这篇文章主要说下jrtplib库数据的收发流程。 数据收发流程 从例子1就可以很好的说明jrtplib的使用是非常简单的&#xff0c;主要分为以下几步 1. 设置会话参数(比如时间戳&am…

同花顺_代码解析_技术指标_C

本文通过对同花顺中现成代码进行解析&#xff0c;用以了解同花顺相关策略设计的思想 CBJX 成本均线 成本价均线不同于一般移动平均线系统&#xff0c;成本价均线系统首次将成交量引入均线系统&#xff0c;充分提高均线系统的可靠性。成本均线不容易造成虚假信号或骗线&#xf…

牛客网项目-开发注册功能

前言 本文是对牛客网项目的总结&#xff0c;本文主要讲解页面注册逻辑 当我们点击首页的注册按钮时&#xff0c;会跳转到注册页面&#xff0c;然后再祖册页面提交账号&#xff0c;密码邮箱后会跳转到首页或者直接登录页面进行登录&#xff0c;这个操作可以自己设定 【设计逻辑…

SAP ABAP BAPI_SALESORDER_CREATEFROMDAT2 成本中心 kostl

BAPI_SALESORDER_CREATEFROMDAT2提供参数无成本中心字段&#xff0c;所以需要用扩展字段实现。 BAPE_VBAK&#xff1a; BAPE_VBAKX VBAKKOZ VBAKKOZX 封装扩展结构&#xff1a; DATA: LS_EXTENSION TYPE BAPIPAREX, LT_EXTENSION TYPE TABLE OF BAPIPAREX. DATA: LS_B…

目标检测论文解读复现之十一:基于特征融合与注意力的遥感图像小目标检测

前言 此前出了目标改进算法专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读最新目标检测算法论文&#xff0c…