尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
C语言程序内存分段
在程序运行时操作系统会给每个进程分配一套独立虚拟地址把地址划分为不同段不同段放不同性质的数据。操作系统给进程的虚拟内存空间对所有语言都是一样但是高级语言在原来内存之上又封装了一层自己的内存模型。C语言直接操作系统系统内存分段几乎无中间层。本文将主要讲述C语言的内存分段以及注意事项。一、进程内存七段代码段.text只读数据段(.rodata)初始化数据段(.data)未初始化数据段(.bss)堆(heap)栈(stack)内核空间二、各段总结表1、汇总表段存放内容读写生命周期栈stack局部变量、形参读写函数调用期间自动回收堆heapmalloc申请内存读写手动malloc、free未初始化数据段(.bss)未初始化/0的全局/static变量读写进程全程启动清零初始化数据段.data初始化非0全局/static变量读写进程全程只读数据段rodata字符串字面量、全局const常量只读进程全程代码段.text程序机器指令只读整个进程运行期间2、使用window上进行内存测试#includestdio.h#includestdlib.h// ---------------- 全局变量 ----------------intg_init100;// .data 初始化全局intg_uninit;// .bss 未初始化全局constintg_const666;// .rodata 全局只读常量char*str_lithello rodata;//字符串字面量存rodatastaticints_init200;// .data static初始化staticints_uninit;// .bss static未初始化voidfunc(intparam){intlocal_stack;// 栈局部变量staticintstatic_local99;// .data函数内staticstaticintstatic_local_no;// .bss函数内static未初始化int*p_heap(int*)malloc(sizeof(int));//堆内存printf(函数func内部地址\n);printf(函数参数param-》栈 : %p\n,param);printf(局部变量local_stack-》栈: %p\n,local_stack);printf(static局部(初始化) : %p\n,static_local);printf(static局部(未初始化) : %p\n,static_local_no);printf(malloc堆地址 : %p\n,p_heap);free(p_heap);}intmain(void){intmain_local;// main的局部变量栈printf(【.text 代码段】main函数地址 : %p\n,main);printf(【.rodata全局const】g_const : %p\n,g_const);printf(【.rodata字符串字面量】 : %p\n,hello rodata);printf(【.data已初始化全局】g_init : %p\n,g_init);printf(【.data static全局】s_init : %p\n,s_init);printf(【.bss未初始化全局】g_uninit : %p\n,g_uninit);printf(【.bss static全局】s_uninit : %p\n,s_uninit);printf(\nmain函数栈变量\n);printf(main局部变量main_local : %p\n,main_local);func(10);return0;}运行结果3、特殊情况说明(1、static不论是写在函数内还是函数外都不会存在栈static全局-有初始化的放在.data,无初始化放在.bss(2)、const变量位置区分局部const只是编译期检查内存依然可写不是放rodata#includetools.h#includewindows.hconstintglobal_i10;//全局const-》放在.rodatavoiddef_f(){constintdef_i20;//局部const-》放在栈printf(局部const-修改前的值为%d\n,def_i);int*p(int*)def_i;//取const变量地址强制去掉const属性*p200;//通过指针修改栈上内存printf(局部const-修改后的值为%d\n,def_i);}intmain(){SetConsoleOutputCP(65001);SetConsoleCP(65001);printf(全局const的值为%d\n,global_i);def_f();return0;}运行结果(3)字符串字面量字符串常量修改程序会崩溃字符串拷贝到数组上是可以修改的intmain(){SetConsoleOutputCP(65001);SetConsoleCP(65001);char*p1abc;//abc存放到rodatap1是栈指针//p1[0]1;charp2[]123;//把字符串复制到栈数组可修改printf(数组修改前第一个字符的值为%c\n,p2[0]);p2[0]x;printf(数组修改后第一个字符的值为%c\n,p2[0]);return0;}运行结果4大数组局部大数组char buf [1010241024]放到栈会栈溢出全局大数组char buf [1010241024]放到bss段不会栈溢出动态分配char * bufmalloc(1010241024):放到堆5编译优化影响开启-O优化后有些常量会被直接编译进指令不一定存在rodata6共享库so动态链接动态库的段会映射到进程虚拟地址空间多个进程共享.text只读段。三、各段详解1、代码段.text存放编译后的机器指令就是写的函数代码属性只读防止程序运行修改指令特点编译时就确定大小运行时不能修改2、只读数据段.rodataread-only data存放字符串常量、const修饰的全局常量局部的const int a10是栈上变量不在rodata只有全局/静态const常量放在rodata属性只读写操作直接报段错误segment fault3、初始化数据段.data存放已经初始化的全局变量、static静态变量不为0属性可读可写程序启动时把可执行文件中初始值拷贝到该段。在嵌入式系统中Flash Rom中存在.data初始值镜像给RAM-data段用的初始化模板上电拷贝到RAM。RAM中data则存放已初始化全局/static上电从Flash复制过来4、未初始化数据段.bssBlock Started by Symbol存放全局变量、static变量没有初始化或者初始化为0特点不占可执行文件大小exe文件中不存这些0程序启动操作系统直接把这段内存全部清0.所以定义很大的全局数组放bssexe不会变大。5、堆heap位置bss上方向上增长地址变大来源malloc、realloc、calloc、free手动申请释放特点完全手动管理内存操作系统不会自动回收大小运行时动态变化没有自动清零calloc除外常见问题内存泄漏、野指针、越界6、栈stack位置高地址向下增长地址变小存放局部变量、函数形参、函数返回地址、临时变量特点函数进入自动分配函数退出自动回收不需要手动free栈空间很小Linux默认一般8MB左右栈越界直接段错误栈溢出stack overflow–不要定义巨大局部数组会直接栈溢出崩溃7、内核空间最高地址用户程序不能直接访问操作系统内核使用访问直接报错。四、实际开发注意事项1、栈空间有限千万不要局部定义超大数组大数组用全局bss或malloc堆2、不要修改字符串字面量3、static局部变量不在栈函数多次调用会保留上次值多线程环境下容易出现线程不安全4、堆内存一定要free否则内存泄漏free之后不要再继续使用指针野指针5、.bss全局变量自动初始化为0栈局部变量不会清零默认为随机垃圾值一定手动初始化。voidf(){inta;//栈随机值不是0}intg;//全局bss自动为06、区分虚拟地址和物理地址打印出来的指针地址都是虚拟地址不是真实物理内存地址。操作系统做地址转换7、const局部变量只是编译期保护可以绕过编译修改但是属于C语言未定义行为UB尽量不要写。
RELATED

相关推荐

架构演进,先做一条可回退的最小链路

架构演进,先做一条可回退的最小链路

架构演进,先做一条可回退的最小链路 遗留系统改造可以先从一条边界清晰的链路开始。防腐层的目标是隔离模型差异,而不是把所有旧代码一次搬走。 上个月,团队需要为老单体系统接入全新的微服务化结算中台。 初出茅庐的工程师在老系统的 OrderS…

📅 2026/9/15 13:30:38
Galileo 2+Klipper快速配置指南:gear_ratio 9:1与rotation_distance 47.088深度解读

Galileo 2+Klipper快速配置指南:gear_ratio 9:1与rotation_distance 47.088深度解读

Galileo 2Klipper快速配置指南:gear_ratio 9:1与rotation_distance 47.088深度解读 【免费下载链接】Galileo2 项目地址: https://gitcode.com/gh_mirrors/ga/Galileo2 Galileo 2 是一套广受 3D 打印玩家欢迎的开源挤出机项目,包含可直装 Voron …

📅 2026/9/8 16:59:37
AMD Ryzen终极调试指南:SMUDebugTool免费开源SDT工具从入门到精通

AMD Ryzen终极调试指南:SMUDebugTool免费开源SDT工具从入门到精通

AMD Ryzen终极调试指南:SMUDebugTool免费开源SDT工具从入门到精通 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址:…

📅 2026/9/15 7:18:43
MORE NEWS

更多资讯

📰

碰碰好评卡核心功能实现逻辑与落地部署实战及常见问题排查指南

在电商用户运营场景中,碰碰好评卡是一种轻量化的用户反馈激励工具,通过权益激励引导消费者提交真实购物评价,帮助商户提升店铺权重与商品转化率。本文从技术视角出发,完整讲解碰碰好评卡的架构设计、核心功能实现、多端部署流程以…

📰

碰碰好评卡功能实现全流程实战开发指南 附核心源码与踩坑总结

背景与价值 围绕关键词「碰碰好评卡」,本文结合CSDN内容发布场景,从行业背景、核心问题、解决方案、实施步骤和常见误区五个维度展开。 知识库参考 抖客 抖音返利3.0 #1:标题:抖客 抖音返利3.0 标签:抖客 抖音返利3.0 …

📰

灵魂无处安放?归属感缺失的底层逻辑与落地方法

1. 这个标题到底在问什么“为什么有人会觉得灵魂无处安放”——这句话乍一看像是一句文艺感慨,但如果把它当成一个真实存在的心理状态来拆解,它其实指向了一个非常具体的体验:一个人明明身处正常的生活轨道里,有工作、有社交、有日…

📰

帕德博恩数据集多模态耦合机制与工况编码解析

简介:本资源是一份面向机械故障诊断、智能运维及工业大数据方向研究者与工程师的帕德博恩轴承数据集深度解读文档,聚焦多模态数据理解与故障分类建模基础。文档系统梳理了K0##(健康)、KA##(外圈)、KB##&…

📰

SpringBoot+Spring Security+Redis后台管理系统部署与登录认证避坑指南

简介:这是一套面向Java后端开发者与计算机专业学生的完整网站后台管理系统源码,基于Spring Boot、MyBatis、Spring MVC、Spring Security与Redis构建,适合希望掌握企业级Web开发技术栈、理解各组件协同工作的中高级学习者。项目以Spring Boot…

📰

IIS迁移选型与避坑:四类Web服务器对比实战

简介:面向需要在 Windows 环境下快速搭建轻量 Web 服务、尤其是调试 ASP 页面的用户,这份小型工具包提供了一套替代 IIS 的简易思路。它围绕可执行服务程序、页面样式表与说明网页组织,适合个人开发者、教学演示或旧项目维护场景,…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬