【高质量C++/C总结6】内存管理——堆(stack)栈(heap)

C++ STL容器适配器:stack、queue、priority_queue原理与实现 在C++标准模板库(STL)中,容器适配器是一种基于设计模式的重要组件,它通过封装现有序列容器来提供特定的数据访问语义。其核心原理是适配器模式,即在不修改原有容器接口的基础上,通过限制和重新组合操作,实现栈(LIFO)、队列(FIFO)和优先级队列等特定数据结构。这种设计不仅提升了代码的复用性和安全性,还通过底层容器的灵活选择优化了性能。例如,stack默认基于deque实现,避免了vector扩容时的数据搬迁开销;priority_queue则基于vector和堆算法,高效支持按优先级调度。在工程实践中, 阅读详情

说在开始:

我提炼了《C++ Primer》、《侯捷C++》、《高质量程序设计指南——C/C++语言》等资料中的重要部分,并总结成此博文。其中涉及到许多我个人对C++的理解,如若有不合理之处,还请朋友们多多指出,我会虚心接受每一个建议。

作者:尹豆(憨豆酒),联系我yindou97@163.com,熟悉图形学,图像处理领域,本章代码: https://github.com/douysu/computer-graphics-notes

内存分配方式——堆栈(stack)和栈(heap)

堆栈(stack)

存在于某一个作用域的存储空间。在函数执行期间,函数内部分局部变量和形参都会创建在堆栈上。在函数执行结束时,存储单元会自动在堆栈中清退。由系统分配,分配速度比较快,效率比较高。一般情况不会出现错误,但是有时会出现退栈溢出。

堆(heap)

由系统提供的一块全局的内存空间,程序在运行过程中需要使用malloc或者new申请任意数量的内存,可称为动态内存分配,使用非常灵活但是也非常出现问题。

两者申请方式

void function(){
    Object a;//在堆栈(stack)
    Object *b=new Object();//在堆(Heap)
}

在这段代码中应该注意,a是存在堆中的,在函数消亡后就不可在使用,尤其注意不可以使用对象a的引用,因为引用一个不存在的对象是不太现实的。 而对象b在程序的运行过程中都会存在,直到手动delete或者free后才不可以在使用。

两者申请过程

stack:只要栈还有足够的剩余空间,系统都会给程序进行分配,否则分配失败

heap:应用程序调用操作系统OS的内存管理模块,搜索其中是否含有符合要求的空闲连续字节内存块。在操作系统中,多次进行动态内存分配后,会产生许多内存碎片,操作系统可能首先需要整理内存碎片,然后才能分配成功,在这种情况下就需要很长的时间。

如果对上面的话理解起来有困难,可以参考一下书籍《操作系统》中内存管理的章节。

空间大小比较

stack:是一块内存连续区域,也就是说,栈的首地址和大小都是一开始定义好的。如果申请空间大于栈的空间就会出现溢出的现象。默认的堆空间都不大,大概是1M,2M。

heap:在操作系统中,是不连续的内存区域,是由操作系统的空闲内存链表来控制的,(关于空闲内存链表的问题,可以查看操作系统的书籍),堆的大小由虚拟内存影响,堆的申请空间比较大,但是有时申请速度可能比堆慢。

堆栈中的存取内容

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

heap:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。

其他堆栈内容

(1)还有另外一种内存分配方式:从静态存储区分配,这段内存在程序编译的时候就是确定的,在程序的整个运行期间都是存在的,例如全局变量和static变量等等。

(2)在动态内存中,开发人员需要检查返回值和捕获异常,来确保内存分配是否成功,这需要额外的开销。千万不要认为这种这种开销是可以避免的。千万不要因小失大。

(3)动态内存创建的对象需要手动delete,甚至在删除后还会继续使用,或者根本就不回删除,这时程序就会出现内存泄漏等现象。同时这些错误也是不容易被发现的。

Android Native Heap内存泄漏排查:从工具链到实战场景全解析 内存管理是软件性能优化的核心基础,其原理在于操作系统如何为进程分配和回收物理与虚拟内存资源。在Android开发中,Java堆内存因有垃圾回收机制而备受关注,但Native堆内存作为供C/C++代码使用的独立区域,其分配与释放完全依赖开发者控制,一旦管理不当,将引发更隐蔽的内存泄漏问题,直接影响应用稳定性和用户体验。从技术价值看,掌握Native内存分析能力是高级性能优化的关键,尤其在处理多媒体渲染、AI推理等重度依赖Native库的场景时。本文聚焦Android Native Heap,系统介绍从adb 阅读详情

相关推荐

华为C/C++编程安全实战:从内存管理到防御性编程的工业级指南

C/C++作为系统级编程语言,其核心价值在于对硬件资源的直接控制能力,这为实现极致性能与确定性提供了基础。然而,这种能力也带来了内存泄漏、缓冲区溢出等安全风险,尤其在嵌入式、通信设备等资源受限且要求高可靠性的场景下,安全问题更为突出。理解指针、内存管理等底层原理,并掌握静态分析、动态测试等工程实践方法,是构建安全可靠系统的关键。本文聚焦于工业级C/C++开发中的安全编码规范与防御性编程实践,深入剖析了内存安全、指针安全等核心挑战,并介绍了如何通过智能指针、地址消毒器(ASan)等工具构建主动防御体系,旨在帮

weixin_34327223的博客 337

c++堆(heap)、栈(stack)与内存管理

Stack Stack是存在于某作用域(scope)的一块内存空间(memory space)。例如当你调用函数,函数本身即会形成一个stack用来放置它所接收的参数,以及返回地址。 在函数本体(function body)内声明的任何变量,其所使用的内存块都取自上述stack Heap Heap或谓system heap,是指由操作系统提供的一块global内存空间,程序可动态分配(dynamic allocated),从中获得若干块(blocks) 例子: class Complex {...}; ..

一个搬运知识的笨小孩 1956

Unity开发者必备:C++核心知识精讲与面试实战指南

内存管理和多线程是计算机系统编程中的基础概念,它们直接影响程序的性能和稳定性。内存管理涉及堆栈分配、垃圾回收机制,而多线程则关乎并发控制和数据同步。这些底层原理在游戏开发中尤为重要,尤其是在Unity引擎中,它们直接关系到渲染管线、物理引擎和Native插件交互的效率。掌握C++中的指针、引用、虚函数表等核心知识,不仅能帮助开发者深入理解Unity底层架构,还能在性能优化和Native插件开发中发挥关键作用。本文聚焦内存管理、多线程等高频考点,通过实战示例解析其在Unity开发中的具体应用,助力开发者构建稳

weixin_30919571的博客 697

【数据结构】什么是堆?什么是栈?C++的具体实现

这是一篇对堆栈数据从内存管理和数据结构深层次理解的博客,强调注意二者的区别,内有代码实现

m0_46566336的博客 1099

从漏洞利用开发入门到精通:系统学习路径与实战指南

漏洞利用开发是网络安全领域的核心技术之一,它涉及将软件缺陷转化为可控执行流的过程。其原理基于对程序内存管理、CPU指令执行和操作系统机制的深刻理解,通过精心构造的输入数据实现代码执行或权限提升。这项技术的核心价值在于帮助安全人员深入理解攻击链,从而设计更有效的防御方案,并应用于渗透测试、漏洞研究、安全产品开发等场景。在实践层面,掌握系统底层原理、逆向工程、编程及漏洞缓解技术是构建完整知识体系的四大支柱。本文以栈溢出和堆溢出等常见漏洞类型为切入点,结合调试器与反汇编工具的使用,系统梳理了从基础到进阶的学习路线

diaomeijiao3430的博客 466

C语言性能优化实战:11个硬实力拆解与代码实证

在计算机编程领域,性能优化是衡量代码质量的核心指标之一。其原理在于通过算法改进、内存管理和指令级优化等手段,减少程序执行时间和资源消耗。技术价值体现在提升系统响应速度、降低硬件成本和增强用户体验。应用场景广泛覆盖操作系统内核、嵌入式系统、游戏引擎和高频交易等对延迟和资源有极致要求的领域。本文聚焦C语言,通过指针运算、手动内存管理、数据对齐和SIMD指令等具体技术,结合代码示例,深入剖析其为何在性能竞争中保持优势,为开发者提供一套可验证的优化实践指南。

weixin_33889245的博客 412

C++中的栈(Stack)和堆(Heap)

在C++中,堆(heap)和栈(stack)是两种用于存储数据的内存区域。

专注于 Qt/C++ 应用开发和机器视觉领域的开源项目分享。期待与您共同进步! 2635

缓冲区溢出漏洞深度解析:从原理到实战修复的5种高危模式

缓冲区溢出是计算机安全领域最经典且持续存在的内存破坏漏洞。其核心原理在于程序向预分配的内存区域写入数据时,未进行有效的边界检查,导致数据溢出到相邻内存区域,从而可能覆盖关键的控制数据(如函数返回地址)。这种底层内存管理机制的缺陷,使得攻击者能够劫持程序执行流程,实现任意代码执行,对系统安全构成极高威胁。在软件开发、嵌入式系统及网络服务等广泛的应用场景中,因编码疏忽或对输入验证不足而引入的此类漏洞屡见不鲜。本文聚焦于【基于堆栈的缓冲区溢出】和【整数溢出】等关键模式,结合工程实践,系统阐述其成因、危害及系统的修

weixin_30448603的博客 430

c++ 栈(Stack)和堆(Heap)

栈是一种先进后出(LIFO,Last In First Out)的数据结构,它用于存储局部变量、函数调用的返回地址等信息。

2402_88047672的博客 1261

C/C++内存错误检测利器:AddressSanitizer(libasan)原理与实战指南

在C/C++开发中,内存错误是导致程序崩溃、数据损坏等严重问题的主要根源。这类错误通常包括内存越界、释放后使用、内存泄漏等,因其隐蔽性和难以复现而成为开发者的痛点。其检测原理基于编译时插桩和运行时监控,通过在程序运行时维护一个“影子内存”映射来实时追踪内存状态,从而精准定位非法访问。这项技术的核心价值在于将传统调试中难以捕捉的“幽灵”错误转化为可定位、可分析的详细报告,极大提升了内存安全问题的排查效率。在工程实践中,它被广泛应用于单元测试、持续集成流水线以及复杂系统的调试阶段,成为保障软件质量的重要工具。本

weixin_33827590的博客 269

编译原理:目标程序运行时的活动

活动(Activation)是程序执行的基本单位。活动定义:过程(函数)的一次执行从调用开始到返回结束有自己的执行环境和生命周期有明确的开始和结束有自己的局部数据可以嵌套调用其他活动遵循后进先出的顺序C程序:int x = 1;foo(x);return 0;bar(b);main活动开始main调用foo,main活动暂停foo活动开始foo调用bar,foo活动暂停bar活动开始bar返回,bar活动结束。

梁辰兴的博客 92

C语言修行之基础篇(十四)管理内存:栈(stack)、堆(heap)、数据区(.data)

C语言中所有变量和常量所使用的内存只有三种情况1、相同点:三种获取内存的方法,都可以给程序提供可用内存,都可以用来定义变量给程序用。2、不同点:栈内存对应C语言中的普通局部变量;堆内存完全是独立于我们的程序存在和管理的;数据段对于程序来说对应C程序中的全局变量和静态局部变量,函数内部临时使用,出了函数不会用到,就定义局部变量堆内存和数据段几乎拥有完全相同的属性,大部分时候是可以完成替换的。但是生命周期不一样。堆内存的生命周期从malloc开始到free结束;

weixin_43564241的博客 3653

TSP旅行商问题 145个城市 C++解决

解决有145个城市的旅行商问题,解决方法-遗传算法。

二进制漏洞利用实战:从栈溢出到堆利用的完整攻防指南

二进制漏洞利用是网络安全领域的核心技术之一,其核心原理是通过精心构造的输入数据,篡改程序的正常执行流或数据流,从而劫持控制权。在内存安全层面,栈溢出、堆溢出、格式化字符串等经典漏洞模型,都源于对程序内存布局的深入理解。现代操作系统部署了NX/DEP、ASLR、Stack Canary、PIE等漏洞缓解技术,这要求攻击者必须掌握相应的绕过思路,例如通过信息泄露获取关键地址,或利用ROP技术执行已有代码。这些技术的工程价值在于,它们不仅是CTF竞赛的解题关键,更是真实世界漏洞挖掘与利用的基石。在应用场景上,从基

weixin_30878501的博客 427

英飞凌TLF35584 SBC实战:手把手教你配置WDG看门狗与ERR监控(基于AUTOSAR架构)

本文详细介绍了基于AUTOSAR架构的英飞凌TLF35584 SBC芯片WDG看门狗与ERR监控功能的配置方法。通过硬件平台搭建、寄存器级配置、AUTOSAR模块集成及诊断策略优化,帮助开发者快速掌握关键配置技巧,提升嵌入式系统的安全性和可靠性。

weixin_30256901的博客 474

SpringBoot多线程查询实战-查询库中所有数据多线程实现

但是,在数据量较大且服务器资源足够的情况下,多线程方法通常能够显著提高查询效率。此外,由于它是同步执行的,没有利用并行处理的能力,所以在处理大量数据时可能会比较慢。这个方法采用了分页查询的方式,每次只获取一部分数据,从而避免了内存溢出的问题。然而,它也是同步执行的,没有利用多线程或并行处理的能力。如果每次分页查询的数据量仍然很大,或者需要查询的轮数很多,那么这种方法的效率可能仍然会受到限制。​ ​ ​在比较这三种方式的效率时,我们需要考虑几个关键因素:数据量的大小、查询操作的复杂性、以及并行处理的能力。

勇敢牛牛,不怕困难! 4809

内存安全漏洞深度解析:堆损坏与格式字符串攻击原理与防御

内存安全是软件安全的基石,其核心在于确保程序对内存的访问严格遵循既定规则。当程序读写超出预定边界时,便会引发内存安全漏洞,其中堆损坏和格式字符串攻击是两类经典且危害巨大的漏洞类型。堆损坏源于对动态内存(堆)的手动管理不当,攻击者可利用堆缓冲区溢出、释放后使用等漏洞操纵堆管理器内部结构,最终实现任意地址写入并劫持程序控制流。格式字符串攻击则利用了格式化输出函数(如printf)的解析特性,当用户输入被直接用作格式字符串时,攻击者可通过%n等格式符向任意地址写入数据,或利用%p、%s泄露关键内存信息,从而绕过地

weixin_33985507的博客 291

麒麟系统下的多媒体革命:VLC在kylinV10上的性能优化与调试技巧

本文详细介绍了在麒麟kylinV10系统上优化VLC多媒体播放性能的实战技巧,特别针对飞腾FT-2000/4硬件平台。从源码编译调优到硬件加速配置,提供全面的性能提升方案,帮助开发者在国产操作系统上构建高效媒体播放环境。

weixin_29168675的博客 457

C语言变长数组(VLA)详解:从内存原理到工程实践

在C语言编程中,数组作为基础数据结构,其内存分配机制直接影响程序性能与稳定性。传统数组要求在编译时确定长度,这源于栈内存的静态分配特性——编译器需在函数调用前预留固定空间。C99标准引入的变长数组(VLA)打破了这一限制,允许在运行时根据变量值动态分配栈内存,为处理不确定长度的数据提供了新思路。这一特性在嵌入式系统、算法实现等场景中具有实用价值,尤其适合生命周期短暂且大小可控的临时缓冲区。然而,VLA的移植性争议与栈溢出风险也需警惕,开发者需在GCC/Clang的灵活支持与MSVC的兼容限制间权衡。本文聚焦

weixin_30236595的博客 337

Codesys电子凸轮功能块MC_CamIn的masteroffset和slaveoffset参数的使用

问题1:在Codesys使用作轴电子凸轮时,MC_CamTableSelect的参数设置为MasterAbsolute=1,SlaveAbsolute=1,此设置为绝得模式, 此时主从轴当前位置都不为零时,此时Masteroffset=0、slaveOffset=0,凸轮启时出现突变,实轴无法启动。问题分析:在觉得模式下,主轴位置和从轴为是对应凸轮表的相位的,Masteroffset=0、slaveOffset=0,启动点时在主轴位置=0,从轴位置=0的点启动,此时主轴当前位置不为零则主从轴位置发生突变,

weixin_43587371的博客 1800

【电弧故障检测算法全解析,电弧串扰问题分析和解决算法】

本文系统分析了电弧故障检测算法及串扰问题解决方案。电弧检测主要采用时频域分析和机器学习方法,通过提取高频噪声、波形畸变等特征实现故障识别。针对电弧串扰问题,提出了自适应滤波、盲源分离和时频联合分析等算法。研究给出了Python和C语言的算法实现示例,包括高频能量检测、过零率计算和陷波滤波器设计。最后指出算法优化方向:实时性提升可采用滑动窗口FFT和硬件加速;抗干扰增强需结合硬件滤波;机器学习扩展可引入随机森林等分类器。该研究为电弧故障检测系统开发提供了完整的技术路线。

syttt的专栏 891

【关于JVM原理】

JVM(Java Virtual Machine,Java 虚拟机)是 Java 程序的运行环境。它最大的贡献是实现了 “一次编写,到处运行”(跨平台),因为 JVM 屏蔽了底层操作系统的差异,Java 代码被编译成字节码(.class 文件),由不同平台上的 JVM 解释执行。

livemegoodboy的博客 209

华为OD机试 - 素数之积 - 数学问题(Java 2025 A卷 100分)

每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天优快云在线答疑。

学Java,找哪吒 2133

C++从入门到精通:环境搭建、核心语法与内存管理实战指南

编程语言是软件开发的基石,其核心在于将人类逻辑转化为机器可执行的指令。C++作为一门经典的静态类型、编译型语言,其设计哲学强调对系统资源的直接控制与高性能计算。通过编译器将源代码转换为机器码的过程,涉及预处理、编译、汇编和链接四个关键阶段,这赋予了开发者对程序执行细节的深度掌控能力。这种底层控制力使得C++在操作系统、游戏引擎、高频交易系统等对性能有极致要求的领域具有不可替代的技术价值。本文以环境搭建和核心语法为切入点,详细解析了从GCC/MSVC编译器配置、VSCode IDE使用,到变量、函数、类等基础

weixin_30268921的博客 346

9.23华为OD机试真题 新系统 - 世界杯徽章换购 (Java/Py/C/C++/Js/Go)

9.23华为OD机试真题 新系统 - 世界杯徽章换购 (Java/Py/C/C++/Js/Go)

算法大师! 1561

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

上一篇: 【高质量C++/C总结5】const常用用法-提高程序的健壮性
下一篇: 【高质量C++/C总结7】内存管理——常见的内存错误及对策
尹豆(douysu)
博客等级 码龄9年 151粉丝 41原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值