程序的内存分段

程序的内存分段

当执行程序的运行命令后,操作系统会给程序分配它所需要的内存,并划分成以下内存段供程序使用:

text 代码段:

​ C代码被翻译成二进制指令后存储在可执行文件中,当可执行文件被操作系统执行时,它会把里面的二进制指令(编译后的代码)加载到这个内存段,它里面的内容决定了程序如何执行,为了避免程序被破坏、修改,所以它的权限是只读

​ 该内存段分为两个部分(权限一样):

​ r-x:二进制指令 r–:常量数据

​ r-xp r–p

注意:该内存段的内容如果被强制修改会产生段错误(非法使用内存)。

data 数据段:

​ 存储的是初始化过的全局变量

​ 存储在内存段的变量,被const修饰后,就会改存储到text内存段,变成真正的常量。

bss 静态数据段:

​ 存储的是未初始化的全局变量

​ 操作系统把程序被加载到内存后,会把该内存段进行初始化,也就是所有字节赋值为零,所以其默认值不是随机,而是零

heap 堆:

​ 该内存段由程序员手动调用内存管理函数(malloc/free),进行分配、释放,它的分配释放受程序员的控制,适合存储一些需要长期使用的数据。

​ 它的大小不受限制,理论上能达到物理的上限,所以适合存储大量的数据。

​ 该内存段无法取名字,也就是无法与标识符建立联系,必须与指针配合使用。(比如malloc的返回值就是内存块首地址 void*)

stack 栈:

​ 存储的是局部变量、块变量(例如数组)

​ 该内存段会随着程序的执行自动的分配(定义局部变量、块变量)、释放(函数执行完毕自动释放局部变量、块变量),虽然使用比较方便,但它的释放不受程序控制,长期使用的数据不能存储在栈内存中。

​ 该内存的大小有限,在终端执行: ulimit -s 可以查看当前系统栈内存的使用上限,我们使用虚拟机ubuntu的栈内存使用上限是8192kb也就是8M,一旦超过这个限制就会产生段错误。可以使用ulimit -s 命令设置栈内存的使用上限(下次开机不想回到默认值,需修改配置文件)。
在这里插入图片描述
修改:
/etc/security/limits.conf

etc/rc.local

静态内存:

​ 当程序完成编译 text、data、bss 三个内存段的大小就确定,在程序运行期间大小不会有任何变化,可以使用size命令查看程序的这三个内存段的大小。

#include<stdio.h>
int num;
int main(int argc,const char* argv[])
{
	printf("hello world!");
	return 0;
}

#include<stdio.h>
int num=1;
int main(int argc,const char* argv[])
{
	printf("hello world!");
	return 0;
}

#include<stdio.h>
const int num=1;
int main(int argc,const char* argv[])
{
	printf("hello world!");
	return 0;
}

在这里插入图片描述
初始化后:data+4,bss-4
const+初始化:data-4,text+4

动态内存:

​ heap、stack两个内存段,会随着程序的执行动态变化。

​ 当程序运行时,/proc/程序编号/maps 文件里记录程序执行过程中内存的使用情况,程序运行结束这个文件就消失了。

ps aux命令查看所有进程的编号,getpid函数可以获取当前进程的编号

<think>好的,我现在需要帮助用户了解C语言中的内存分段概念及机制。首先,我得回忆一下自己之前学过的相关知识,然后结合用户提供的引用内容来组织回答。 用户提到了四个引用,其中引用1和引用3直接涉及内存相关内容。引用1提到内存分布是C语言的重点,而引用3详细解释了内存对齐和内存分段的原因,这部分信息很重要。引用4提到了指针和内存分配,可能和内存分段有关联,但用户的问题更关注分段机制,所以可能需要优先处理引用1和3的内容。 首先,我需要明确内存分段的基本概念。内存分段指的是程序内存中的不同区域划分,比如代码段、数据段、BSS段、堆、栈等。每个段的作用不同,比如代码段存放指令,数据段存放全局变量等。这部分知识可能需要结合引用3中提到的内存对齐机制,但用户的问题更侧重于分段而非对齐,所以重点应放在各个段的功能上。 接下来,我需要确定各个内存段的具体内容。比如代码段(.text)存储可执行指令,数据段(.data)存储已初始化的全局变量和静态变量,BSS段(.bss)存储未初始化的全局变量和静态变量,堆用于动态内存分配,栈用于局部变量和函数调用。这些内容需要清晰地区分,并且可能需要用例子来说明,比如引用2中的变量n和r可能存储在栈中,而动态分配的内存则在堆里。 然后,内存分段的原因。引用3提到内存对齐和CPU的寻址方式,这可能涉及到分段存在的必要性。比如,CPU的寻址方式可能需要不同的段来区分代码和数据,或者出于安全考虑,防止代码被修改。需要结合引用3中的内容,说明分段如何帮助提高效率和安全性。 此外,还需要考虑用户可能的疑问,比如内存分段内存分页的区别,或者如何在实际编程中观察到这些段。不过用户的问题主要是详解分段,因此需要集中在机制和结构上。 在组织内容时,要确保按照逻辑顺序,先介绍各个段,再说明原因,最后可能的应用或影响。同时,使用用户提供的引用作为支持,比如引用3中提到的CPU寻址方式作为分段一个原因,引用4中动态内存分配与堆的关系。 最后,生成相关问题时要围绕内存分段,可能涉及其他内存管理概念、实际应用中的问题、或与其他机制的对比。比如,如何查看各段的大小,内存分段程序性能的影响等。 需要确保回答符合用户的要求:使用中文,行内公式用$...$,独立公式用$$...$$,正确引用标记,结构清晰,分步骤解释,真实可靠。</think>### C语言内存分段详解 在C语言中,程序运行时占用的内存空间会被划分为多个逻辑段,每个段存储特定类型的数据。这种分段机制不仅与编译器实现相关,还与操作系统和硬件架构的设计紧密联系。以下是内存分段的核心内容: --- #### 1. **内存分段的五大区域** 内存分段主要分为以下五个区域: - **代码段(.text)** 存储可执行指令(即编译后的机器码),此区域通常是只读的,防止程序意外修改指令[^3]。 - **数据段(.data)** 存储已初始化的全局变量和静态变量(如`static int a = 10;`)。这些变量的值在程序启动时即被确定。 - **BSS段(.bss)** 存储未初始化的全局变量和静态变量(如`int b;`或`static int c;`)。此区域在程序加载时会被初始化为零值[^1]。 - **堆(Heap)** 用于动态内存分配(如`malloc`或`free`操作)。堆的地址从低到高增长,需要手动管理内存,分配失败可能引发内存泄漏[^4]。 - **栈(Stack)** 存储局部变量、函数参数及返回地址。栈的地址从高到低增长,由系统自动管理。例如,函数调用时局部变量`int n`和`int r`会被压入栈中[^2]。 --- #### 2. **内存分段的原因** 内存分段的机制主要基于以下需求: 1. **安全性** 代码段设为只读可防止指令被篡改,数据段和栈的分离可避免越界访问。 2. **效率优化** 通过区分不同数据类型的存储区域,提高CPU缓存命中率,例如频繁访问的栈数据与静态数据分开存储。 3. **硬件支持** CPU对内存的访问通常以“段”为单位,例如x86架构的段寄存器(如CS代码段、DS数据段)直接支持分段机制。 --- #### 3. **内存分段的实际示例** 通过以下代码分析变量存储位置: ```c #includ
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值