C/C++程序的内存分区

c/c++程序的内存分区模型详解 内存分区 运行之前 我们要想执行我们编写的c程序,那么第一步需要对这个程序进行编译。 预处理:宏定义展开、头文件展开、条件编译,这里并不会检查语法 编译:检查语法,将预处理后文件编译生成汇编文件 汇编:将汇编文件生成目标文件(二进制文件) 链接:将目标文件链接为可执行程序 在没有运行程序前,也就是说程序没有加载到内存前,可执行程序内部已经分好... 阅读详情


正确理解C/C++程序的内存分区,对程序员来说是最基本的要求。
网络上流形两大版本内存分区,分别为:

  1. 五大内存分区:堆、栈、全局/静态存储区、自由存储区和常量存储区。
  2. 五大内存分区:堆、栈、全局/静态存储区、字符串常量区和代码区。
    且不论以上两种分区孰是孰非,孰优孰劣,个人认为具体的内存分区和编译器有很大关系,不同编译器对内存的划分都不尽相同,但也大同小异。
    综合对比,查阅相关资料,提出个人对C/C++程序的内存分区的认识。可划分为四大内存分区:堆、栈、静态存储区和代码区,即内存四区。

堆区

由开发人员手动申请,手动释放,若不手动释放,程序结束后由系统回收,生命周期是整个程序运行期间。使用malloc或者new进行堆的申请,堆的总大小为机器的虚拟内存的大小。
说明:new操作符本质上是使用了malloc进行内存的申请,new和malloc的区别如下:
(1)malloc是C语言中的函数,而new是C++中的操作符。
(2)malloc申请之后返回的类型是void*,而new返回的指针带有类型。
(3)malloc只负责内存的分配而不会调用类的构造函数,而new不仅会分配内存,而且会自动调用类的构造函数。

注:理解机器虚拟内存看:https://zhuanlan.zhihu.com/p/96098896
malloc 是 memory(内存)+ allocation(分配)两个英文拼凑的。读['mælɒk]

栈区

由系统进行内存的管理。主要存放函数的参数以及局部变量。
在函数完成执行,系统自行释放栈区内存,不需要用户管理。
整个程序的栈区的大小可以在编译器中由用户自行设定,VS中默认的栈区大小为1M,可通过VS手动更改栈的大小。
64bits的Linux默认栈大小为10MB,可通过ulimit -s临时修改。

静态存储区

静态存储区内的变量在程序编译阶段已经分配好内存空间(虚拟内存地址,在程序执行时会映射到对应的物理地址处)并初始化(在程序开始执行时,在main方法运行前,就已经就位了)。这块内存在程序的整个运行期间都存在,它主要存放静态变量、全局变量和常量。
注意:
(1)这里不区分初始化和未初始化的数据区,是因为静态存储区内的变量若不显示初始化,则编译器会自动以默认的方式进行初始化,即
静态存储区内不存在未初始化的变量。
(2)静态存储区内的常量分为常变量和字符串常量(即字符串字面值),一经初始化,不可修改。常变量 分为编译期常变量和运行期常变量,区别是一个是在函数外定义的(存储在静态存储区),一个是在函数内定义的(存储在栈区),这里说的函数内定义的常变量只是用const一个限定词修饰的变量,如 const int a = 2。 如果是在函数内用static const 修饰变量,static在前,首先被它修饰的变量 首先是静态的,然后才是常变量,上面我们也说了静态变量是存储在静态存储区。
(3)字符串常量存储在静态存储区的常量区,字符串常量的名称即为它本身,属于常变量。这是说的就是 如 “abc”,“hello”,"中国人"的字符 串字面值。
(4)数据区的具体划分,有利于我们对于变量类型的理解。不同类型的变量存放的区域不同。后面将以实例代码说明这四种数据区中具体对应的变量。
(5)被const修饰的变量,可能存储在栈区,静态存储区,要看定义的地方。如果不涉及常量指针或指针常量 ,只是 如 const int a = 2;这种形式 ,是不允许修改 右值的。

代码区

代码区:存放程序编译后的二进制代码(存放二进制的机器指令),和 除字符串字面值外的其他类型的字面值都在代码区, 不可寻址(不可以寻址, 指的是不能通过&获得其地址),这里说的不可寻址是指的这些位于代码区的字面值不可寻址,而位于代码区的函数等都是可以寻址的。
int a = 0;//静态全局变量区
char *p1; //编译器默认初始化为NULL
void main()
{
    int b; //栈
    char s[] = "abc";//s在栈,"abc"在字符串常量区,尾部加\0,在函数体内执行到此处时,把"abc\0",从静态存储区拷贝一份数据到栈区,赋值给s.
    char *p2 = "abc";//字符串字面值123456存储在字符串常量区,尾部加\0(这里的字符串字面值会被优化后,在静态存储区只存一份),p2在栈上,在函数体内执行到此处时,把"abc\0",的首地址返给p2。现在的多数编译器都要求这种形式声明的字符串,前面加 const ,变成 const char *p2。防止修改静态存储区的字符串常量。而上面char s[] 操作修改的话,是修改自己栈里的那份数据,不是修改的静态存储区里的。
    static int c =0; //c在静态变量区,0为文字常量,在代码区
    const int d=0; //栈
    static const int d;//静态常量区
    p1 = (char *)malloc(10);//分配得来得10字节在堆区。
    strcpy(p1, "abc"); //123456放在字符串常量区,编译器可能会将它与p2所指向的"abc"优化成一个地方
}
当"abc" 被 加载到静态存储区时,是按照字符数组的方式存储在静态存储区的,会在其后面自动添加\0;
注:这里的"abc" 被优化后在静态存储区里只有一份。

总结

在理解C/C++内存分区时,常会碰到如下术语:数据区,堆,栈,静态存储区,静态区,常量区,常变量区,全局区,字符串常量区,静态常量区,静态变量区,文字常量区,代码区等等,初学者被搞得云里雾里。在这里,尝试捋清楚以上分区的关系。
数据区包括:堆,栈,静态存储区。
静态存储区包括:常量区(静态常量区),全局区(全局变量区)和静态变量区(静态区)。
常量区包括:字符串常量区和常变量区。
可以说,C/C++内存分区其实只有两个,即代码区(存放二进制的机器指令)和数据区。

避开这些坑!海天MA1600注塑机数据采集项目经验分享 本文分享了海天MA1600注塑机数据采集项目的实战经验。针对KEBA控制器接口不开放的难题,项目采用专用网关进行协议转换,并详细剖析了网络部署、ModbusTCP配置、数据准确性保障及现场运维中遇到的典型陷阱与解决方案,为同类工业物联网项目提供宝贵参考。 阅读详情

相关推荐

深入解析:el-table合并单元格

  在企业级应用开发中,我们经常需要处理复杂的数据展示需求。在构建复杂的数据展示后台时,我们常常需要将表格中具有相同属性的行进行视觉上的合并,以提升信息的聚合度和可读性。在 Element Plus 的 el-table 组件中,span-method 属性是实现单元格合并的核心机制,允许开发者自定义单元格的合并逻辑,开发者可以通过实现自定义合并策略来满足各种负责需求。  合并行的本质是通过计算相邻行数据的相似性,确定满足合并的单元格范围,然后通过 DOM 操作将多个单元格合并为一个。这种操作在前端数据可视

独泪了无痕 231

C/C++程序内存的分配

一、一个C/C++编译的程序占用内存分为以下几个部分: 栈区(stack):由编译器自动分配与释放,存放为运行时函数分配的局部变量、函数参数、返回数据、返回地址等。其操作类似于数据结构中的栈。 堆区(heap):一般由程序员自动分配,如果程序员没有释放,程序结束时可能有OS回收。其分配类似于链表。 全局区(静态区static):存放全局变量、静态数据、常量。程序结束后游戏厅释放。全局区分为已初...

cherrydreamsover的博客 4万+

Unity游戏开发:从零开始适配Nintendo Switch的完整指南

本文详细介绍了如何使用Unity进行Nintendo Switch游戏开发的完整流程,包括开发环境搭建、Unity工程适配、手柄与硬件特性开发、存储与性能优化等关键步骤。特别强调了Switch SDK的配置、输入系统改造和内存优化技巧,帮助开发者高效完成跨平台适配。

vodka的博客 1069

不止八股---CPP(进程内存布局,malloc原理)

内核空间用户空间栈:栈用于维护函数调用的上下文,离开了栈函数调用就没法实现,在10.2节中将对栈作详细的介绍。栈通常在用户空间的最高地址处分配,通常有数兆字节的大小。堆:堆是用来容纳应用程序动态分配的内存区域,当程序使用 malloc 或 new 分配内存时,得到的内存来自堆里。堆会在10.3节详细介绍。堆通常存在于栈的下方(低地址方向),在某些时候,堆也可能没有固定统一的存储区域。堆一般比栈大很多,可以有几十至数百兆字节的容量。

qq_63253400的博客 813

FUEL算法解读(一)——框架解读,思维导图可以很清晰看懂算法启动框架,已更新完,图太大放不上来链接在文末

一图看懂FUEL算法节点框架!!!

weixin_43793717的博客 2786

TMP112/TMP102温度传感器驱动开发与嵌入式实战

数字温度传感器是嵌入式系统环境感知的核心器件,其通过I²C等标准总线实现高精度、低功耗测温。原理上依赖ΔΣ模数转换与二进制补码数据格式,结合寄存器配置实现模式控制、阈值报警与功耗管理。技术价值体现在±0.5°C级精度、1μA级静态电流及SOT-563超小封装带来的系统集成优势。广泛应用于工业MCU热监控、电池物联网终端、医疗电子温度补偿及汽车ECU板级测温等场景。本文围绕TMP112/TMP102展开,深入解析寄存器协议、硬件接口约束、HAL驱动分层设计、FreeRTOS任务调度及生产级校准方法,覆盖从芯片

weixin_35756690的博客 674

C++类内存分布

书上类继承相关章节到这里就结束了,这里不妨说下C++内存分布结构,我们来看看编译器是怎么处理类成员内存分布的,特别是在继承、虚函数存在的情况下。 工欲善其事,必先利其器,我们先用好Visual Studio工具,像下面这样一步一步来: 先选择左侧的C/C++->命令行,然后在其他选项这里写上/d1 reportAllClassLayout,它可以看到所有相关类的内存布...

weixin_30919919的博客 792

手把手教你理解ARM SoC中的PPU:电源管理IP的配置与实战避坑指南

本文深入解析ARM SoC中的PPU(Power Policy Unit)电源管理IP,提供详细的配置指南与实战避坑技巧。从PPU基础架构、寄存器配置到与PCSM的协同工作,全面介绍如何优化电源管理策略,解决常见配置误区,并分享高级调试与性能优化方法,助力工程师提升低功耗SoC设计效率。

weixin_28693447的博客 481

C++内存

C++ 内存分为栈、堆、全局 / 静态区、常量区、代码区,其中堆内存需要手动管理是核心重点;堆内存操作要遵循new→delete的配对原则,现代 C++ 优先用智能指针替代裸指针;常见内存问题(泄漏、野指针、双重释放)的核心规避思路:“自动管理” 替代 “手动管理”,操作指针前做合法性检查。

2501_94473255的博客 561

游戏经济数值模型的搭建过程——以标准卡牌游戏为例

一、总体规划 1.玩家分类 首先我们按照下表对玩家进行分类 付费能力即为充值额度;充值行为比如购买月卡/购买钻石;消费行为比如用钻石抽卡 在这里我们假设玩家是理性的,即玩家会以追求更高的性价比为目标进行充值与消费(即小R会优先买首冲+月卡,而不是买一个无用的无属性皮肤) 不同类型玩家之间的差异,实际上就主要由这些行为的差异而决定。 注:早期游戏制作的时候,活跃程度也是区分玩家类型的一个重要依据。不过目前现在游戏中有各种手段抹平了不同活跃玩家的差异(体力限制,活跃时间长的收益递减)..

dudu3332的博客 4229

机器学习(十九):梯度提升回归(GBR)

机器学习中的梯度提升回归算法原理与案例实战。

全栈川川 5157

C/C++内存分布深度解析

C/C++内存管理包括栈、堆、内存映射段、数据段和代码段等区域。栈用于局部变量和函数调用,堆用于动态内存分配。C语言使用malloc/free管理内存,而C++引入new/delete操作符,后者能自动调用构造函数和析构函数。operator new通过malloc实现但会抛出异常,比malloc更可靠。定位new可在已分配内存上显式调用构造函数。内存泄漏指程序未能释放不再使用的内存,可能导致性能下降甚至崩溃。malloc/free与new/delete的主要区别在于后者是操作符且能自动调用构造/析构函数,

2502_92236850的博客 804

ENS160传感器原理图设计,已量产(空气质量传感器)

ENS160 是一款集成式数字空气质量传感器,核心优势源于 “MEMS 传感元件 + 内置微处理器” 的架构。

不脱发的程序猿 573

C/C++程序运行的五种内存分区

1.简介 在C/C++程序运行时,所使用的内存分为**代码区(Code)、堆区(Heap)、栈区(Stack)、全局/静态存储区(static)、常量存储区(const)**五个分区。注意此处的堆和栈并不是指数据结构 2.详解 (1)代码区 这个区域存放程序包含的所有函数体的二进制代码 (2)堆区 由用户代码分配/释放,下面的语句将会分配堆上的存储空间: char *p = (char *)m...

qq_42885747的博客 2780

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

C/C++ 程序内存分区详解:从实验到工具验证

程序运行时,内存被划分为多个逻辑区,各司其职:通过代码打印变量地址,结合工具验证存储位置: 运行结果: 3. 内存布局示意图 4. 工具验证:nm、size、objdump (1) 使用 查看符号表 输出: 符号类型: → 只读数据段(.rodata)。 → 已初始化数据段(Data)。 → 未初始化数据段(BSS)。 (2) 使用 查看段大小 输出: Data段:628 字节(包含用户变量和编译器内部数据)。 BSS段:12 字节(仅用户变量占 4 字节)。 (3) 使用

acxcr_007的博客 397

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

C/C++编译的程序占用的内存分区

C/C++编译的程序占用的内存分区 1、栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 2、堆区(heap)—一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。 3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的

vallenlsl的专栏 399

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

正确的理解C/C++程序的内存分区

导读正确的理解C/C++程序的内存分区,是合格程序猿的基本要求。 网络上流形两大版本内存分区,分别为: 五大内存分区:堆、栈、全局/静态存储区、自由存储区和常量存储区。 五大内存分区:堆、栈、全局/静态存储区、字符串常量区和代码区。 且不论以上两种分区孰是孰非,孰优孰劣,我认为具体的内存分区和编译器有很大关系,我想不同编译器对内存的划分都不尽相同,但也大同小异。 综合对比,查阅相关资料,提

pengf_wuxiaowu的博客 1016

深入理解C/C++程序的内存分区管理

上,可以直接运行内存管理的示例代码观察实际地址分布。常量存储的特殊性:全局const变量位于静态区不可修改,而局部const变量实际存储在栈中,通过指针仍可间接修改(不推荐)。内存地址观察技巧:通过打印变量地址可以发现,栈地址向低地址增长,堆地址向高地址扩展,静态区地址相对固定。常量区的混淆:字符串常量与const变量存储位置不同,前者必定在静态区,后者根据作用域可能位于栈或静态区。多线程影响:静态局部变量的初始化在C++11后是线程安全的,但全局变量的初始化顺序仍可能引发"静态初始化顺序灾难"问题。

FrostfireStag78的博客 835

C/C++程序内存分区详解与优化实践

程序内存管理是软件开发的核心基础,理解内存分区原理对编写高效稳定代码至关重要。从计算机体系结构角度看,进程内存通常划分为代码区、数据区、堆区和栈区等核心区域,每个区域具有不同的生命周期和访问特性。代码区存放只读的机器指令,全局/静态区管理程序生命周期数据,栈区实现函数调用的自动内存管理,而堆区支持动态内存分配。合理利用这些分区特性可以优化程序性能,例如通过栈变量提升访问速度,使用堆内存处理大数据,或利用常量区共享重复数据。在C/C++开发中,特别需要注意栈溢出、内存泄漏等典型问题,结合智能指针、内存池等技术

weixin_33428613的博客 253
上一篇: springboot 配置兼容 https和http 访问
下一篇: C/C++什么是字面值常量
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值