C内存管理

来源:互联网 发布:聪明的网络语怎么说 编辑:程序博客网 时间:2024/05/22 15:00

C语言中内存主要分为三部分,  堆,  栈 ,   数据区


一:栈 (先进后出)(栈是从高地址向低地址方向增长)

普通局部变量.所有的自动变量、函数形参都存储在栈中

特点:运行自动分配回收:栈是系统自动管理,不需要程序员去处理。

    反复使用 栈内存在程序中是一块空间地址,程序反复使用这块地址

脏内存 由于栈的反复使用,每次使用后程序不去清理,分配时原来的值还会存在

临时性 (函数不能返回栈变量的指针,因为这个空间是临时的)

栈溢出 操作系统给予栈的大小是固定的,函数中不断分配栈内存会导致栈内存使用完,然后会溢出。

注意: 1: 每个线程都有自己的栈

2: 不能将一个栈变量的地址通过函数的返回值返回,因为栈的生命周期比较短。例如局部变量使用后,函数结束时程序会释放相应的栈内存。

3: 栈不会很大,程序中直接将较大的数组保存在函数内栈变量中,会导致栈溢出。例如:在某个函数中char array[1024*1024*1024] = {0};

4: C语言中函数参数入栈的顺序是从右到左

5: C语言中形参和实参之间是值传递。


二:堆     (先进先出)

特点:操作系统堆管理器:堆管理器是操作系统的一块模块,内存分配灵活。

大块内存 :是一块容量很大的操作系统空间,每个进程按照各自需求进行申请,使用结束后要注意释放。内存大小远远大于栈内存。一般比较复杂的数据类型都是放在堆中。

手动申请释放 :malloc 申请 memset 内存初始化   free释放

脏内存 :堆内存也会重复使用,在释放前不会清除,

临时性 :生命周期在malloc 和 free 之间,在此之外无法访问。

内存泄露 :申请的堆内存没有释放,会导致内存泄露,

堆在内存中位于bss区和栈区之间



三:代码段,数据段,bss段

代码段(text): 程序可执行部分,直观理解就是函数堆叠组成

C语言中定义字符串时 char *p = "hello";   字符串“hello” 实际分配在代码段。因为这个字符串是常量字符串,不是变量字符串。

const关键字用来定义常量,常量就是不能被改变的量。const有两种实现方法:

第一种就是编译将const修饰的变量放在代码段去以实现不能修改(普遍见于各种单片机的编译器)

第二种就是由编译器来检查以确保const型的常量不会被修改,实际上const型的常量还是和普通变量一样放在数据段的(gcc中就是这样实现的)。


数据段(data): C语言程序中的全局变量(全局变量时程序的数据,局部变量是函数的数据)

显示初始化为非0 的全局变量和静态局部变量放在数据段(即static 修饰的局部变量)()


bss段(未初始化数据区): 被初始化为0的数据段。

int a = 0;     //a在全局已初始化数据区 
char *p1;     //p1在BSS区(未初始化全局变量) 
main() 
{
int b;     //b在栈区
char s[] = "abc"; //s为数组变量,存储在栈区,
//"abc"为字符串常量,存储在已初始化数据区
char *p1,p2;   //p1、p2在栈区
char *p3 = "123456"; //123456\0在已初始化数据区,p3在栈区 
static int c =0;   //C为全局(静态)数据,存在于已初始化数据区
//静态数据会自动初始化
p1 = (char *)malloc(10); //分配得来的10个字节的区域在堆区
p2 = (char *)malloc(20); //分配得来的20个字节的区域在堆区
free(p1);
free(p2);