内存分区模型

embedded/2025/1/18 4:55:37/

栈区(stack)

函数调用。编译器自动分配释放,存放 函数的参数值局部变量

堆区(heap)

动态分配的变量。由程序员动态分配和释放,使用new 和 delete

全局/静态存储区(Data Segment &  BSS  Segment)

Data Segment 数据段

存放初始化了的 全局变量和 静态变量

BSS  Segment 

存放未初始化的全局变量和静态变量  实际不占用磁盘空间

代码区(Text Segment )

文本区/只读区

存放程序的二进制代码和常量

具体的根据实际情况变化

栈(Stack)和堆(Heap)

栈(Stack)和堆(Heap)是两种不同的内存管理区域,它们在内存分配、释放、生命周期管理以及使用方式上都有显著的区别。以下是对栈和堆的详细对比:

1. 内存分配和释放

栈(Stack)
  • 分配:由编译器自动分配内存。当函数被调用时,函数的参数、局部变量等自动在栈上分配内存。

  • 释放:由编译器自动释放内存。当函数返回时,栈上的内存自动释放,不需要程序员干预。

  • 示例

    void function() {int localVar = 10;  // 局部变量在栈上分配内存// 当函数返回时,局部变量的内存自动释放
    }
堆(Heap)
  • 分配:由程序员通过newmalloc等函数动态分配内存。

  • 释放:由程序员通过deletefree等函数手动释放内存。如果程序员忘记释放,会导致内存泄漏。

  • 示例

    int* ptr = new int[10];  // 动态分配内存
    // 使用内存
    delete[] ptr;  // 手动释放内存

2. 生命周期管理

栈(Stack)
  • 生命周期:栈上的内存生命周期与函数调用栈的生命周期相同。当函数返回时,栈上的内存自动释放。

  • 示例

    void function() {int localVar = 10;  // localVar的生命周期从函数调用开始,到函数返回结束
    }
堆(Heap)
  • 生命周期:堆上的内存生命周期由程序员控制。程序员需要在适当的时候手动释放内存。

  • 示例

    int* ptr = new int[10];  // 动态分配内存
    // 使用内存
    // 在适当的时候释放内存
    delete[] ptr;

3. 内存管理方式

栈(Stack)
  • 管理方式:栈的内存管理是自动的,由编译器在编译时确定。栈的操作方式是后进先出(LIFO),内存分配和释放非常高效。

  • 优点

    • 高效:栈的内存分配和释放非常快,因为栈的操作是连续的,不需要复杂的管理。

    • 自动管理:编译器自动管理栈上的内存,程序员不需要手动干预。

  • 缺点

    • 大小有限:栈的大小通常有限,一般在几MB到几十MB之间,取决于操作系统和编译器的设置。

    • 栈溢出:如果栈上的局部变量过多或递归调用过深,可能会导致栈溢出。

堆(Heap)
  • 管理方式:堆的内存管理是动态的,由程序员在运行时通过newmallocdeletefree等函数进行管理。堆的内存分配和释放相对复杂,需要更多的管理开销。

  • 优点

    • 大小灵活:堆的大小通常较大,可以动态分配和释放内存,适合存储大量数据或生命周期较长的数据。

    • 灵活管理:程序员可以灵活地控制内存的分配和释放,适合复杂的内存管理需求。

  • 缺点

    • 效率较低:堆的内存分配和释放相对较慢,因为需要进行更多的管理操作。

    • 内存泄漏:如果程序员忘记释放内存,会导致内存泄漏,影响程序的性能和稳定性。

    • 碎片化:频繁的分配和释放内存可能导致内存碎片化,影响内存的利用率。

4. 使用场景

栈(Stack)
  • 适用场景

    • 局部变量:函数内部的局部变量,生命周期与函数调用相同。

    • 递归调用:递归函数的参数和局部变量,每次递归调用都会在栈上分配新的内存。

    • 临时数据:临时使用的数据,不需要长期存储。

堆(Heap)
  • 适用场景

    • 动态数据结构:如动态数组、链表、树等,需要在运行时动态分配和释放内存。

    • 大型数据:存储大量数据,如图像、视频等,栈的大小有限,不适合存储大型数据。

    • 生命周期较长的数据:需要在多个函数之间共享的数据,栈上的内存生命周期与函数调用相同,不适合存储生命周期较长的数据。

总结

  • 栈(Stack)

    • 自动管理:编译器自动分配和释放内存。

    • 高效:内存分配和释放非常快。

    • 大小有限:栈的大小通常有限,容易发生栈溢出。

    • 适用场景:局部变量、递归调用、临时数据。

  • 堆(Heap)

    • 动态管理:程序员通过newmallocdeletefree等函数手动管理内存。

    • 灵活:可以动态分配和释放内存,适合存储大量数据和生命周期较长的数据。

    • 效率较低:内存分配和释放相对较慢,容易发生内存泄漏和碎片化。

    • 适用场景:动态数据结构、大型数据、生命周期较长的数据。

理解栈和堆的区别对于编写高效、健壮的C++程序至关重要。合理使用栈和堆可以提高程序的性能和稳定性。


http://www.ppmy.cn/embedded/154858.html

相关文章

SpringBoot3+Vue3开发台球计时系统

项目介绍 台球计时系统可以帮助我们自动计算开台时间(从开始到结束的时间段)、自动计算开台费用、结账后生成订单记录进行留存、也可以导出订单记录。 主要功能包含:球桌管理、开台、结账、查看占用明细、查看球台订单、订单管理、查看订单…

SpringBoot 基于 Redisson 分布式锁实现

1. 分布式锁 1.1 为什么要使用分布式锁 以下是使用分布式锁的一些主要原因: 保持数据一致性: 在分布式系统中,数据一致性是至关重要的。使用分布式锁可以防止并发更新导致的数据不一致问题,确保数据在所有节点之间保持一致避免…

【开源分享】nlohmann C++ JSON解析库

文章目录 1. Nlohmann JSON 库介绍2. 编译和使用2.1 获取库2.2 包含头文件2.3 使用示例2.4 编译 3. 优势4. 缺点5. 总结参考 1. Nlohmann JSON 库介绍 Nlohmann JSON 是一个用于 C 的现代 JSON 库,由 Niels Lohmann 开发。它以易用性和高性能著称,支持 …

Canvas简历编辑器-选中绘制与拖拽多选交互方案

Canvas简历编辑器-选中绘制与拖拽多选交互方案 在之前我们聊了聊如何基于Canvas与基本事件组合实现了轻量级DOM,并且在此基础上实现了如何进行管理事件以及多层级渲染的能力设计。那么此时我们就依然在轻量级DOM的基础上,关注于实现选中绘制与拖拽多选交…

基于Java的百度AOI数据解析与转换的实现方法

目录 前言 一、AOI数据结构简介 1、官网的实例接口 2、响应参数介绍 二、Java对AOI数据的解析 1、数据解析流程图 2、数据解析实现 3、AOI数据解析成果 三、总结 前言 在当今信息化社会,地理信息数据在城市规划、交通管理、商业选址等领域扮演着越来越重要的…

采用海豚调度器+Doris开发数仓保姆级教程(满满是踩坑干货细节,持续更新)

目录 一、采用海豚调度器+Doris开发平替CDH Hdfs + Yarn + Hive + Oozie的理由。 1. 架构复杂性 2. 数据处理性能 3. 数据同步与更新 4. 资源利用率与成本 6. 生态系统与兼容性 7. 符合信创或国产化要求 二、ODS层接入数据 接入kafka实时数据 踩坑的问题细节 三、海…

pytest-instafail:让测试失败信息即时反馈

pytest-instafail:让测试失败信息即时反馈 前言一、简介二、优势三、安装与使用3.1 未安装时运行情况3.2 安装3.3 已安装时运行情况3.3 pytest.ini 配置选项 四、对比 总结 前言 当测试用例数量庞大时,定位测试失败的原因往往耗时费力。此时,…

网络学习记录5

二、学习网络知识: 1、透传: ①“透传”指的是数据在传输过程中不被交换机或其他网络设备解析、修改或处理,而是直接从一个端口传输到另一个端口。这种传输方式保持了数据的原始性和完整性,常用于需要高速、低延迟的数据传输场景…