内存和函数

news2025/1/21 10:19:09

程序的内存布局 

        Linux默认情况下将高地址的1GB空间分配给内核,用户进程使用剩下2GB或者3GB的内存空间。在用户空间里,也有很多地址区间有特殊的地位,一般来讲,应用程序使用的内存空间里有如下"默认"的区域

        1、栈:用于维护函数调用的上下文,离开了栈函数调用就没法实现。栈通常在用户空间的最高地址处分配,通常有数兆字节的大小。

        2、堆:用来容纳应用程序动态分配的内存区域,当程序使用malloc或new分配内存时,得到的内存来自堆里。堆通常在于栈的下方(低地址方向),在某些时候,堆也可能没有固定统一的存储区域。堆一般比栈大很多,可以有几十至数百兆字节的容量。

        3、可执行文件影像:这里存储着可执行文件在内存里的影像,由装载器在装载时将可执行文件的内存读取或映射到这里

        4、保留区:保留区并不是一个单一的内存区域,而是对内存中受到保护而禁止访问的内存区域的总称呼,例如,大多数操作系统里,极小的地址通常都是不允许访问的,如NULL。通常C语言将无效指针赋值为0也是出于这个考虑,因为0地址上正常情况下不可能有有效的可访问数据。

        如图1是Linux下一个进程里典型的内存布局。

                         图1  Linux进程地址空间布局

        在图1中,有一个没有介绍的区域:"动态链接库映射区",这个区域用于映射装载的动态链接库。在Linux下,如果可执行文件依赖其他共享库,那么系统就会为它在从0x40000000开始的地址分配相应的空间,并将共享库载入到该空间。

栈和调用惯例

        栈是现代计算机程序里最为重要的概念之一,几乎每一个程序都使用了栈,没有栈就没有函数,没有局部变量,也就没有我们如今能够看见的所有的计算机语言。

        在经典的计算机科学中,栈被定义为一个特殊的容器,用户可以把数据压入栈中(入栈),也可以将已经压入栈中的数据弹出。

        在计算机系统中,栈则是一个具有以上属性的动态内存区域。程序可以将数据压入栈中,也可以将数据从栈顶弹出。压栈操作使得栈增大,而弹出操作使得栈减少。

        在经典的操作系统里,栈总是向下增长的。在i386下,栈顶由称为esp的寄存器进行定位。压栈的操作使得栈顶的地址减小,弹出的操作使得栈顶的地址增大。图2是一个程序栈实例。

                图2 程序栈实例

        这里的栈底的地址是0xbfffffff,而esp寄存器标明了栈顶,地址为0xbffffff4。在栈上压入数据会导致esp减小,弹出数据使得esp增大。相反,直接减少esp的值也等效于在栈上开辟空间,直接增大esp的空间等效于在栈上回收空间。

        栈在程序运行中具有举足轻重的地址。最重要的,栈保存了一个函数调用所需要的维护信息,这常常被称为堆栈帧或者活动记录。堆栈帧一般包括如下几方面的内容:

        1、函数的返回地址

        2、临时变量:包括函数的非静态局部变量以及编译器自动生成的其他临时变量

        3、保存的上下文:包括在函数调用前后需要保持不变的寄存器

        

        在i386中,一个函数的活动记录用ebp和esp这两个寄存器划定范围。esp寄存器始终指向栈的顶部,同时也就指向了当前函数的活动记录的顶部。而相对,ebp寄存器指向了函数活动记录的一个固定位置,ebp寄存器又被称为帧指针。一个很常见的活动记录所图3所示。

                         图3  活动记录

        在参数之后的数据(包括参数)即是当前函数的活动记录,ebp固定在图中所示的位置,不随这个函数的执行而变化,相反地,esp始终指向栈顶,因此随着函数的执行,esp会不断变化。固定不变的ebp可以用来定位函数活动记录的各个数据。在ebp之前首先是这个函数的返回地址,它的地址是ebp-4,再往前是压入栈中的参数,它们的地址分别是ebp-8,ebp-12等,视参数数量和大小而定。ebp所直接指向的数据是调用该函数前ebp的值,这样在函数返回的时候,ebp可以通过读取这个值恢复到调用前的值。之所以函数的活动记录会形成这样的结构,是因为函数本身是如此书写的:一个i386的函数总是这样调用:

        1、把所有或一部分参数压入栈中,如果有其他参数没有入栈,那么使用某些特定的寄存器传递

        2、把当前指令的下一条指令的地址压入栈中

        3、跳转到函数体执行

        其中第2步,第3步由指令call一起执行。跳转到函数体之后即开始执行函数,而i386函数体的"标准"开始是这样的:

        *        push ebp:把ebp压入栈中(称为old ebp)

        *        move ebp, esp:ebp=esp(这时ebp指向栈顶,而此时栈顶就是old ebp)

        *        sub esp,XXX:在栈上分配XXX字节的临时空

        *        push XXX:如有必要,保存名为XXX寄存器

        把ebp压入栈中,是为了在函数返回的时候便于恢复以前的ebp的值。而之所以可能要保存一些寄存器,在于编译器可能要求某些寄存器在调用前后保持不变,那么函数就可以在调用开始时将这些寄存器的值压入栈中,在结束后再取出。不难想象,在函数返回时,所进行的"标准'结尾和"标准"开始正好相反。

        *        pop XXX:如有必要,恢复保存国的寄存器

        *        move esp,ebp:恢复ESP同时回收局部变量空间

        *        pop ebp:从栈中恢复保存的ebp的值

        *        ret:从栈中取得返回地址,并跳转到该位置

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

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

相关文章

疫情可视化part2

前言 这是疫情可视化最开始的文章,有需要了解的可前往查看:https://blog.csdn.net/xi1213/article/details/126824752。 本来说有时间就把这个项目完结了的,结果后面一直有事拖着,直到现在十一月份了才搞完。老样子,先…

F1. 生活在树上(easy version)树,dfs

题目链接 F1. 生活在树上(easy version) 题目背景 本题是 B 组的最后一题,是 F2 题的简单版本,两道题目的解法略有不同。本题和 F2 题在题意上的区别在于本题给定树上的边权,而不是点权。 小智生活在「传智国」&am…

汽车 Automotive > SOME/IP VS DDS调研和未来方向

参考:JASPAR, General incorporated association:What is the conqueror in the SOA platform for the future in-vehicle networks? 目录 SOME/IP介绍参考 DDS介绍 SOME/IP VS DDS 研究方向 SOME/IP介绍参考 汽车Automotive > SOME/…

MAC安全(防MAC泛洪攻击)

一、MAC地址表项分类: 1.1 动态表项:通过对帧内的源MAC进行学习而来,有老化时间 1.2 静态表项:由管理员手工配置,不会老化 1.3 黑洞表项:丢弃特定源MAC或目的MAC,不会老化 静态和黑洞表项不会被动态表项…

类与对象(下篇)

类与对象(下)再谈构造函数回顾构造函数初始化列表explicit 关键字拷贝构造函数也具有初始化列表友元 friend友元函数输入输出流的重载友元类static 成员内部类再谈构造函数 回顾构造函数 在上一篇博客中提到了构造函数,构造函数其主要目的是…

类与对象(中篇)

类中六个默认成员函数构造函数基本概念构造函数特性析构函数基本概念析构函数特性拷贝构造函数基本概念拷贝构造函数特性赋值运算符重载概念引入运算符重载函数的特性部分运算符的重载函数判等赋值前置 、前置--后置、后置--const 成员函数取地址只要生成一个类 ,那…

iOS_Custom Transition Animation 自定义转场动画

文章目录1、push-pop 动画协议2、present-dismiss 动画协议3、实现转场动画协议3.1 动画时长3.2 push or present animation (显示动画)3.3 动画结束3.4 pop or dismiss animation (消失动画)4、UIPresentationController4.1 设置presentVC的frame4.2 present 动画4.3 dismiss …

Docker快速安装Oracle 12c

【Oracle系列3】Docker快速安装Oracle 12c 背景 现在还很多企业用12c,以这个版本为例,介绍docker快速启动Oracle并做实验 步骤 1、docker环境的安装(略) 2、查询镜像,挑选镜像 docker search oracle结果 StoneM…

阿里P8架构师都在学习参考的SpringCloud微服务实战文档

我一直在使用Spring Boot、Spring Data等框架来进行开发工作。 作为一名Spring系列的忠实粉丝,我自然希望能够有更多的开发者参与进来,于是自己坚持写Spring Cloud相关的文章,并且将文章涉及的代码整理后放在GitHub上分享。 这使我得到了很…

【Hack The Box】Linux练习-- Luanne

HTB 学习笔记 【Hack The Box】Linux练习-- Luanne 🔥系列专栏:Hack The Box 🎉欢迎关注🔎点赞👍收藏⭐️留言📝 📆首发时间:🌴2022年11月24日🌴 &#x1f3…

零基础搭建基于知识图谱的电影问答系统

零基础搭建基于知识图谱的电影问答系统一、项目准备二、项目数据三、训练问题分类器四、准备问答模板五、搭建webapp六、问题预处理一、项目准备 首先需要一款python编译器,本人选用的是PyCharm,搭建好Python环境;安装第三方依赖库&#xff…

【Hack The Box】linux练习-- Delivery

HTB 学习笔记 【Hack The Box】linux练习-- Delivery 🔥系列专栏:Hack The Box 🎉欢迎关注🔎点赞👍收藏⭐️留言📝 📆首发时间:🌴2022年11月17日🌴 &#x1…

黄佳《零基础学机器学习》chap1笔记

黄佳 《零基础学机器学习》 chap1笔记 这本书实在是让我眼前一亮!!! 感觉写的真的太棒了! 文章目录黄佳 《零基础学机器学习》 chap1笔记第1课 机器学习快速上手路径—— 唯有实战1.1 机器学习族谱1.2 云环境入门实践:…

ERD Online 4.0.4 元数据在线建模(免费、私有部署)

❝ fix(erd): 修改表名、模块名自定义提示fix(erd): 支持自定义表名显示格式fix(erd): 升级ant到5.0.1版本fix(erd): 修复PDMan导入类型列为空fix(erd): 增加类型列宽度,避免类型显示不全fix(erd): 修复表设计报undefine异常fix(erd): 修复版本比对,出现…

二分搜索算法框架解析

文章目录 一、寻找一个数(基本的二分搜索)二、寻找左侧边界的二分搜索三、寻找右侧边界的二分查找总结 一、寻找一个数(基本的二分搜索) 这个场景是最简单的,可能也是大家最熟悉的,即搜索一个数&#xf…

2023年天津财经大学珠江学院专升本经济学专业课考试大纲

天津财经大学珠江学院2023年高职升本科专业课考试《经济学》考试大纲一、本大纲系天津财经大学珠江学院2023年高职升本科《经济学》课程考试大纲。所列考试范围出自郑健壮、王培才主编的教材《经济学基础(第二版)》,清华大学出版社&#xff0…

win10通过Docker搭建LNMP环境全流程

win10通过Docker搭建LNMP环境全流程 下载安装docker desktop 由于博主环境已经安装好了,一些异常设置,暂且略过 根据官方教程下载docker desktop执行文件.exe 注意尽量不要把docker安装到C盘,除非你的C盘很大,具体可以参考文章 …

初识 Spring 框架

文章目录一、Spring 介绍二、Spring 下载安装三、编写入门程序1.项目文件构架2.引入相关依赖3.创建实体类4.Spring 配置文件5.编写测试类四、控制反转与依赖注入1.控制反转概念2.依赖注入概念3.依赖注入的类型4.依赖注入的应用一、Spring 介绍 Spring 是由 Rod Johnson 组织和…

计算机毕设题目设计与实现(论文+源码)_kaic

毕业设计(论文)题目 高校图书馆座位预约选座微信小程序设计与实现 基于防火墙的访问控制系统的设计与实现 基于区块链的农产品追溯系统设计与实现 学生公寓楼改造布线系统规划与设计 智能家居网络设计与实现“互联网”农村精准扶贫共享平台的设计与实现“智慧健康少儿成长平台”…

Linux内核——门相关入门知识

为什么20位的寻址可以达到1MB? 🔒 点击查看答案 🔒 拆分如下的段描述符: 0000000000000000 00cf9b000000ffff 00cf93000000ffff 00cffb000000ffff 00cff3000000ffff 80008b04200020ab ffc093dff0000001 0040f30000000fff 0000f20…