C++之程序内存分配方式

程序内存布局

现在的应用程序都运行在一个虚拟内存空间里,以32位系统为例,其寻址空间为
4G,大部分的操作系统都将4G内存空间的一部分挪给内核调用,应用程序无法直接
访问这一段内存,这一部分内核地址成为内核态空间,Linux默认将高地址的1G空
间分配给内核,用户使用剩下的3G空间成为用户态空间,用户态空间一般有如下默
认区域:
1. 栈区(stack):由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。
其操作方式类似于数据结构中的栈。
2. 堆区(heap):一般由程序员分配释放,若程序员不释放,程序结束时可能由OS
回收。注意它与数据结构 中的堆是两回事,分配方式倒是类似于链表。
3. 全局/静态区(static):全局变量和静态变量的存储是放在一块的,在程序编译
时分配。
4. 文字常量区:存放常量字符串。
5. 程序代码区:存放函数体(类的成员函数、全局函数)的二进制代码
虚拟内存空间示意图如下:

当执行一个非内置的可执行程序时,加载器会将可执行目标文件中的代码和数据从
磁盘拷贝到内存中
每个Linux程序都会有一个运行时存储器映像,如上图所示。在
可执行文件中段头部表的指导下,加载器将可执行文件的相关内容拷贝到代码和数
据段。
1.在32位系统下,代码段总是从地址0x08048000处开始。
2.数据段是在接下来的下一个4KB对齐的地址处。
3.运行时堆(heap)在读写段之后接下来的第一个4KB对齐的地址,然后向上增长。
4.用户栈(stack)从最大的合法用户地址开始,向下增长。
从3G地址往上的部分是由内核使用的。

程序验证

请看下面这段程序,判断其中的变量位于哪个区域

int a = 0;
char *p1;
int main(){
int b;
char s[] = "123456";
char *p2;
char *p3 = "123456";
static int c = 0;
p1 = new char[10];
p2 = new char[5];
strcpy(p1, "123456");
}

栈与堆的比较

申请后系统的响应

栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异
常提示栈溢出。
堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序
的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将
该结点从空闲结点链表中删除,并将该结点的空间分配给程序。另外,对于大
多数系统,首地址处会记录这块内存空间中本次分配的大小,这样,代码中的
delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定
正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。

申请效率的比较

栈由系统自动分配,速度较快。但程序员无法控制。
堆是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便

申请大小的限制

栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。
这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS
下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如
果申请的空间超过栈的剩余空间时,将提示overflow(栈溢出)。因此,能从栈获得的空
间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用
链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地
址向高地址
。由此可见,堆获得的空间比堆的大小受限于计算机系统中有效
的虚拟内存较灵活,也比较大

堆和栈中的存储内容

栈: 在函数调用时,第一个进栈的是主函数的下一条指令(函数调用语句的下
一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,
数是由右往左入栈的
,然后是函数中的局部变量。注意静态变量是不入栈的。
当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最
开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。
堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容由程序员安
排。

栈与堆的区别

栈与堆的区别在一下六个方面有所不同:
1. 管理方式不同。对于来讲,是由编译器自动管理,无需我们手工控制;对于
来说,释放工作由程序员控制,容易产生memory leak.
2. 空间大小不同。一般来讲在32位系统下,内存可以达到4G的空间,从这个角度
来看堆内存几乎是没有什么限制的。但是对于栈来讲,一般都是有一定的空间
大小的,例如,在VS下,默认的栈空间大小是1M
3. 分配方式。内存有2种分配方式:静态分配和动态分配都是动态分配的,没
有静态分配的堆。静态分配是编译器完成的,比如局部变量的分配。动态分配
由malloc, calloc函数进行分配,但是栈的动态分配和堆是不同的,他的动态分
配是由编译器进行释放,无需我们手工实现。
4. 生长方向。对于来讲,生长方向是向上的,也就是向着内存地址增加的方
向;对于来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。

5. 碎片问题。对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从
造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因
栈是先进后出的,他们是如此的一一对应,以至于永远都不可能有一个内存
块从栈中间弹出,在他弹出之前,在它上面的后进的栈内容已经被弹出。

思维导图

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode:13.罗马数字转整数

13. 罗马数字转整数 - 力扣(LeetCode) 目录 思路: 官解代码: 作者辣眼代码: 每日表情包: 思路: 思路已经很明了了,题目已经给出一般规则和特殊规则(而且题目确保给定的是正确的…

利用 ASP.NET Core 开发单机应用

前言 现在是分布式微服务开发的时代,除了小工具和游戏之类刚需本地运行的程序已经很少见到纯单机应用。现在流行的Web应用由于物理隔离天然形成了分布式架构,核心业务由服务器运行,边缘业务由客户端运行。对于消费终端应用,为了应…

Nginx使用详解

简介Nginx的优缺点Nginx的应用场景Nginx支持的模块Nginx模块配置示例1. **HTTP Access Log 模块**2. **HTTP SSL 模块**3. **HTTP Gzip 模块**4. **HTTP Rewrite 模块** Nginx支持的反向代理协议Nginx反向代理配置Nginx反向代理优点Nginx反向代理配置示例Nginx常用配置参数Ngin…

一文搞懂 springboot 如何融合数据源

1、简介 springboot 支持关系型数据库的相关组件进行配置,包括数据源、连接池、事务管理器等的自动配置。降低了数据库使用的难度,除了 mysql 还支持 Derby、H2等嵌入式数据库的自动配置,MongoDB、Redis、elasticsearch等常用的 NoSQL 的数据…

uWSGI、灰度发布、网站数据指标分析、网站限速

1 案例1:部署Python网站项目 1.1 问题 配置Nginx使其可以将动态访问转交给uWSGI: 1.2 方案 安装Python工具及依赖 安装uWSGI并编写配置文件 1.3 步骤 实现此案例需要按照如下步骤进行。 步骤一: 首先$教学资料目录/python拷贝到虚拟…

Python程序设计 函数

简单函数 函数:就是封装了一段可被重复调用执行的代码块。通过此代码块可以实现大量代码的重复使用。 函数的使用包含两个步骤: 定义函数 —— 封装 独立的功能 调用函数 —— 享受 封装 的成果 函数的作用,在开发程序时,使用…

Unity3d Shader篇(一)— 顶点漫反射着色器解析

文章目录 前言一、顶点漫反射着色器是什么?1. 顶点漫反射着色器的工作原理 二、编写顶点漫反射着色器1. 定义属性2. 创建 SubShader3. 编写着色器程序段4. 完成顶点着色器5. 完成片段着色器 三、效果四、总结 前言 在 Unity 中,Shader 可以用来实现各种…

jmeter设置关联

一、为什么要设置关联? http协议本身是无状态的,客户端只需要简单向服务器请求下载某些文件,无论是客户端还是服务端都不去记录彼此过去的行为,每一次请求之间都是独立的。如果jmeter需要设置跨线程组脚本,就必须设置…

【问题篇】activiti工作流转办并处理备注问题

当处理activiti转办问题时,需要做的就是处理审批人和备注问题。 处理的思路是,先将当前环节标志成转办标签,再通过BUSINESS_KEY_找到流程实例的历史记录,找到最新的一条复制一份出来,表示需要转办到的人的历史记录并设…

APP专项测试方法总结

APP专项测试 1、网络测试 可使用抓包工具辅助网格测试推荐:fiddler,Charles 网络切换: 2G-3G-4G-wifi-网络信号差–无网 网络信号弱: 关注是否出现ANR、crash 2、中断测试 意外中断: 来电;短信&am…

不需英文基础也可以轻松学编程,中文编程开发工具免费版下载,编程工具构件箱之扩展控制面板构件用法

不需英文基础也可以轻松学编程,中文编程开发工具免费版下载,编程工具构件箱之扩展控制面板构件用法 一、前言 编程入门视频教程链接 https://edu.csdn.net/course/detail/39036 编程工具及实例源码文件下载可以点击最下方官网卡片——软件下载——常…

ShardingSphere 5.x 系列【3】分库分表中间件技术选型

有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot 版本 3.1.0 本系列ShardingSphere 版本 5.4.0 源码地址:https://gitee.com/pearl-organization/study-sharding-sphere-demo 文章目录 1. 前言2. My Cat3. ShardingSphe…

C++ 类与对象(下)

目录 1. 再谈构造函数 1.1 构造函数体赋值 1.2 初始化列表 1.3 explicit关键字 2. static成员 2.1 概念 2.2 特性 3.友元 3.1友元函数 3.2 友元类 4. 内部类 5.匿名对象 6.拷贝对象时的一些编译器优化 7. 再次理解类和对象 【本节目标】 1. 再谈构造函数 2. Static成员…

【产品升级】SmartPipe升级到版本2.0

在近一个月的攻关和测试下,SmartPipe软件轴线自动识别算法的性能大幅提升,鲁棒性和稳定性进一步增强。近一年来客户累计反馈的多种复杂管路(包括带有支管管路、带有压瘪段管路、推弯管、装配管、带有复杂孔洞管路等)现在均能够正确…

通过消息队列实现进程之间通信代码

#include <myhead.h> struct msgbuf {long int mtype; char mtext[1024]; }; //定义一个消息大小 #define MSGSIZE sizeof(struct msgbuf)-sizeof(long int) int main(int argc, const char *argv[]) {//1、创建key值以便创建消息队列key_t key ftok("/", k)…

Bootstrap5 图片轮播

Bootstrap5 轮播样式表使用的是CDN资源 <title>亚丁号</title><!-- 自定义样式表 --><link href"static/front/css/front.css" rel"stylesheet" /><!-- 新 Bootstrap5 核心 CSS 文件 --><link rel"stylesheet"…

STM32WLE5JC

Sub-GHz 无线电介绍 sub-GHz无线电是一种超低功耗sub-GHz无线电&#xff0c;工作在150-960MHz ISM频段。 在发送和接收中采用LoRa和&#xff08;G&#xff09;FSK调制&#xff0c;仅在发送中采用BPSK/(G)MSK调制&#xff0c;可以在距离、数据速率和功耗之间实现最佳权衡。 这…

freeswitch对接FunASR实时语音听写

1、镜像启动 通过下述命令拉取并启动FunASR软件包的docker镜像&#xff1a; sudo docker pull \registry.cn-hangzhou.aliyuncs.com/funasr_repo/funasr:funasr-runtime-sdk-online-cpu-0.1.7 mkdir -p ./funasr-runtime-resources/models sudo docker run -p 10096:10095 -i…

【Gephi项目实战-带数据集】利用gephi绘制微博肖战超话120位用户关系图,并计算整体网络指标与节点指标

数据集在评论区&#xff0c;B站演示视频在评论区&#xff01; 简介 最近2天需要用到gephi做社会网络分析&#xff0c;于是从0开始接触gephi并摸索出了gephi的基本使用指南。下面将结合真实的节点文件与边文件&#xff0c;利用gephi绘制社会网络并计算相关测量指标。整个过程会…

我们都是宇宙的奇迹

我们都是独一无二的个体&#xff0c;是宇宙的奇迹 如果我不关注自我&#xff0c;那我在这个宏大的宇宙中有什么意义&#xff1f; 关于你的问题&#xff0c;我想没有一个简单的答案&#xff0c;因为不同的人可能有不同的看法和感受。有些人可能认为&#xff0c;如果不关注自我&…