C语言内存管理:栈与堆的解析
任何一个程序正常运行都需要内存资源用来存放诸如变量、常量、函数代码等等。这些不同的内容所存储的内存区域是不同的且不同的区域有不同的特性。因此我们需要研究内存布局逐个了解不同内存区域的特性。每个 C 语言进程都拥有一片结构相同的虚拟内存不同的程序会占据不同区段的物理内存但经过系统的变换和映射它们的虚拟内存的布局是完全一样的。将其中一个 C 语言进程的虚拟内存放大来看会发现其内部包含区域栈stack堆heap数据段代码段1.1 栈内存栈是现代计算机程序极为重要的组成部分几乎所有的函数调用都依赖于栈进行实现。栈空间中包括函数返回地址记录了函数执行完成后退出函数调用时需要执行的下一条指令命令行参数 ./a.exe abc 123局部变量包括形参函数调用过程中使用的非静态局部变量均默认保存在栈上函数退出后这些变量也会被释放而不可使用保存的寄存器环境变量等保存了函数调用前后需要保持不变的寄存器在程序运行过程中每次执行函数调用都会建立一个栈帧连续的过程调用会让栈不断朝着“栈顶”的方向进行扩展在函数调用完成后栈帧会被自动释放栈也会随之缩减。在大多数体系结构上栈的扩展方向都是由高地址向低地址进行扩展。栈内存有什么特点空间有限尤其在嵌入式环境下。因此不可以用来存储尺寸太大的变量。Linux 栈内存大小为 8M系统为函数分配栈内存时遵循从上高地址往下低地址分配原则由系统规定的我们无法干预每当一个函数被调用时系统将自动分配一段栈内存给该函数用于存放其局部变量每当一个函数有退出时系统将自动回收其栈内存栈空间申请的变量随着函数结束空间自动释放在函数的作用域中定义局部变量是保存在栈中在函数结束时系统会自动回收此函数中创建的栈空间即 return 之后不可再访问函数的局部变量因此返回一个局部变量的地址通常是错误的。# include stdio.h int *add(int a, int b) { int sum; sum a b; return sum; //不能返回函数的局部变量地址 } int main(void) { int *p add(2,5); }1.2 堆内存堆内存heap又被称为动态内存、自由内存简称堆。堆是唯一可被开发者自定义的区段开发者可以根据需要申请内存的大小、决定使用的时间长短等。但又由于这是一块系统“飞地”所有的细节均由开发者自己把握系统不对此做任何干预给予开发者绝对的“自由”但也正因如此对开发者的内存管理提出了很高的要求。对堆内存的合理使用几乎是软件开发中的一个永恒的话题。例如 malloc 它分配的内存来自进程的虚拟内存空间。虚拟内存是操作系统提供的一种内存管理机制它允许程序使用比物理内存更多的内存堆内存基本特征相比栈内存堆的总大小仅受限于物理内存在物理内存允许的范围内系统对堆内存的申请不做限制。相比栈内存堆内存从下往上增长。堆内存是匿名的只能由指针来访问。自定义分配的堆内存除非开发者主动释放否则永不释放直到程序退出。堆内存使用完成后一定要进行手动释放内存否则可能会使内存泄漏导致程序崩溃相关API申请堆内存malloc() / calloc()功能申请堆内存所需头文件#include stdlib.h函数原型void *malloc(size_t size);void *calloc(size_t count, size_tsize);参数size所申请的一块堆内存的大小单位是字节count所申请的堆内存的块数所有的内存块是连续分布的、无间隔的返回值成功返回所申请的内存空间的指针失败NULL#include stdio.h #include stdlib.h int main() { // malloc: 申请一块内存内容是随机的 int *p1 (int *)malloc(5 * sizeof(int)); // calloc: 申请 5 块内存申请的内存会自动清零 int *p2 (int *)calloc(5, sizeof(int)); free(p1); free(p2); return 0; }清零堆内存bzero()功能清零指定内存所需头文件#include strings.h函数原型void bzero(void *s, size_t n);参数s指向要清零的内存的指针n要清零的内存大小单位是字节返回值无#include stdio.h #include stdlib.h #include strings.h int main() { int arr[5] {1, 2, 3, 4, 5}; bzero(arr, sizeof(arr)); // 整块清零 printf(bzero后 arr[0] %d, arr[4] %d\n, arr[0], arr[4]); return 0; }释放堆内存free()功能释放堆内存所需头文件#include stdlib.h函数原型voidfree(void *ptr);参数ptr堆内存指针返回值无#include stdio.h #include stdlib.h int main() { int *p (int *)malloc(3 * sizeof(int)); p[0] 10; p[1] 20; p[2] 30; printf(使用前: p[1] %d\n, p[1]); free(p); // 释放堆内存 p NULL; // 置空防止悬空指针 printf(已释放p NULL\n); return 0; }realloc()申请的堆内存,在原来内存基础上可进行扩容。// 申请堆空间 char *p calloc(1, sizeof(char)); if (p NULL) { printf(calloc failed:); return -1; } char buf[] afjoiajfajflajlfjalflafjslfjsljfls; // 扩容如果不扩容会溢出 char *ptr realloc(p, 100); // 是将空间大小从 1 扩容到 100不是扩容了 100注意malloc()申请的堆内存默认情况下是随机值一般需要用 bzero() 来清零。calloc()申请的堆内存默认情况下是已经清零了的不需要再清零。free()只能释放堆内存不能释放别的区段的内存。释放内存的含义释放内存意味着将内存的使用权归还给系统。释放内存并不会改变指针的指向。释放内存并不会对内存做任何修改更不会将内存清零。内存泄漏示例以下是一个典型的内存泄漏代码在函数中申请堆内存后忘记释放导致每次调用都泄漏内存。#include stdio.h #include stdlib.h void leak_memory() { int *p (int *)malloc(100 * sizeof(int)); // 忘记调用 free(p)函数返回后指针 p 丢失内存却未归还系统 } int main() { for (int i 0; i 100000; i) { leak_memory(); // 每次调用泄漏 400 字节累计约 40MB } printf(程序结束\n); return 0; }后果随着循环不断调用leak_memory()堆内存持续增长而永不释放。在长时间运行的程序如服务器进程中内存泄漏会逐渐耗尽可用内存最终导致系统 OOMOut of Memory或程序崩溃。即使程序结束泄漏的内存在程序运行期间也无法被其他进程使用。如何避免配对使用 malloc 和 free每次调用malloc后确保在合适的时机调用free。使用内存检测工具如 ValgrindLinux或 Dr. MemoryWindows检测内存泄漏。遵循谁申请谁释放原则明确内存的所有权和释放责任避免遗漏。在函数退出前统一释放用goto或if分支确保所有路径都能释放已申请的内存。1.3 堆与栈的区别1、 管理方式不同:栈由系统自动分配空间同时系统自动释放空间。堆需要程序员手动申请并且手动释放并指明大小。在 C 语言中 malloc 函数申请释放 free 函数在 C 中 new 和 delete 实现。2、 存储内容不同:栈在函数调用时栈中存放的是函数中各个参数(局部变量)堆一般是在堆的头部用一个字节存放堆的大小不是必须的。堆中的具体内容由程序员安排。3、 空间大小不同:栈获取空间较小。堆比较灵活比较大。4、 能否产生碎片不同:栈不会产生碎片空间连续。堆采用的是链表的存储方式会产生碎片。5、 分配方式不同:栈静态分配由编译器完成堆动态分配的使用malloc函数6、 分配效率不同栈由系统自动分配速度较快。但程序员是无法控制的。堆由malloc分配的内存一般速度比较慢而且容易产生内存碎片不过用起来方便。7、 生长方向不同栈向低地址扩展的数据结构是一块连续的内存的区域。堆向高地址扩展的数据结构是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的自然是不连续的而链表的遍历方向是由低地址向高地址。

相关新闻

3分钟搞定硬字幕提取:本地免费视频字幕提取神器完全指南

3分钟搞定硬字幕提取:本地免费视频字幕提取神器完全指南

3分钟搞定硬字幕提取:本地免费视频字幕提取神器完全指南 【免费下载链接】video-subtitle-extractor 视频硬字幕提取,生成srt文件。无需申请第三方API,本地实现文本识别。基于深度学习的视频字幕提取框架,包含字幕区域检测、字幕内…

2026/8/9 11:23:12 阅读更多 →
谷歌15亿美元收购AI编程初创公司,AI编程进入工程化时代

谷歌15亿美元收购AI编程初创公司,AI编程进入工程化时代

如果你是一名开发者,最近可能已经感受到了AI编程工具带来的效率冲击。从GitHub Copilot到Cursor,再到各种本地化模型,AI辅助编程正在从“玩具”变成“生产力工具”。但你是否想过,当这些工具背后的技术被科技巨头整合,…

2026/8/9 11:23:12 阅读更多 →
Spark SQL distinct操作性能优化实战指南

Spark SQL distinct操作性能优化实战指南

1. Spark SQL中distinct操作的性能瓶颈解析在Spark SQL的实际应用中,distinct操作是数据去重的常见需求,但也是最容易引发性能问题的操作之一。我曾在多个大数据项目中处理过distinct导致的作业卡顿问题,发现大多数情况下性能瓶颈都源于对dis…

2026/8/9 11:23:12 阅读更多 →

最新新闻

TWS 女生蓝牙耳机新手选型指南:5 款主流机型硬件参数拆解  小耳道用户实测方案

TWS 女生蓝牙耳机新手选型指南:5 款主流机型硬件参数拆解 小耳道用户实测方案

对于零基础入门无线耳机的用户,市面上 TWS 产品硬件规格繁杂,蓝牙版本、ANC/ENC 降噪、腔体人体工学、续航充电等参数概念容易混淆,尤其耳道纤细的用户,常会出现佩戴胀痛、信号断连、降噪功能与使用场景不匹配等问题。本文从硬件底…

2026/8/9 14:16:43 阅读更多 →
Matlab实现多式联运路径鲁棒优化算法

Matlab实现多式联运路径鲁棒优化算法

1. 项目背景与核心挑战多式联运作为现代物流体系中的重要组成部分,其路径优化问题一直是运输管理领域的重点研究方向。在实际运输场景中,需求不确定性和时间窗约束是两个最棘手的现实因素。我们团队最近完成的这个Matlab项目,正是针对这两个痛…

2026/8/9 14:16:43 阅读更多 →
免费获取Montserrat字体:9个字重+3大系列完整指南

免费获取Montserrat字体:9个字重+3大系列完整指南

免费获取Montserrat字体:9个字重3大系列完整指南 【免费下载链接】Montserrat 项目地址: https://gitcode.com/gh_mirrors/mo/Montserrat Montserrat字体是一款完全免费的开源几何无衬线字体,以其优雅的现代设计和丰富的字重选择而闻名全球。这款…

2026/8/9 14:16:43 阅读更多 →
2026年超实用!AI论文写作工具大揭秘,从初稿到定稿全程助力

2026年超实用!AI论文写作工具大揭秘,从初稿到定稿全程助力

还在为写期刊论文、毕业论文或者职称论文头疼吗?人工写论文时,面对堆积如山的资料信息,感觉就像在大海里找针一样难找;再加上各种复杂的格式要求,让人心力交瘁,反复修改更是耗费大量时间和耐心,…

2026/8/9 14:16:42 阅读更多 →
终极Wand专业版解锁指南:如何免费获得完整游戏修改体验

终极Wand专业版解锁指南:如何免费获得完整游戏修改体验

终极Wand专业版解锁指南:如何免费获得完整游戏修改体验 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer 还在为Wand(原WeMod…

2026/8/9 14:16:42 阅读更多 →
大数据专业在校生,可以考哪些证书?一份从入门到进阶的推荐清单

大数据专业在校生,可以考哪些证书?一份从入门到进阶的推荐清单

很多计算机、大数据相关专业的同学,都会在读书期间纠结一个问题:到底要不要考证?考什么证对就业更有帮助?这份清单从国内就业实用性出发,整理了8个值得关注的大数据相关证书,按照能力层次和适用场景分成了四…

2026/8/9 14:15:42 阅读更多 →

日新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/9 0:01:47 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/9 0:01:47 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身,而应重视模型外的系统搭建,即Harness。提出AgentModelHarness的实用公式,详细介绍Harness的四个层次:持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/9 0:03:48 阅读更多 →

周新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/9 0:01:47 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/9 0:01:47 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身,而应重视模型外的系统搭建,即Harness。提出AgentModelHarness的实用公式,详细介绍Harness的四个层次:持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/9 0:03:48 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/8 17:02:44 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/9 0:45:04 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/8 17:02:44 阅读更多 →