C语言内存管理

C语言的内存分配

进程如何使用内存?

毫无疑问,所有进程(执行的程序)都必须占用一定数量的内存,它或是用来存放从磁盘载入的程序代码,或是存放取自用户输入的数据等等。不过进程对这些内存的管理方式因内存用途不一而不尽相同,有些内存是事先静态分配和统一回收的,而有些却是按需要动态分配和回收的。

对任何一个普通进程来讲,它都会涉及到5种不同的数据段,其中数据段、BSS和堆通常是被连续存储的——内存位置上是连续的,而代码段和栈往往会被独立存放

代码段(text segment):用来存放可执行文件的操作指令,也就是说是它是可执行程序在内存中的镜像。代码段需要防止在运行时被非法修改,所以只准许读取操作,通常,代码区是可共享的(即另外的执行程序可以调用它),因为对于频繁被执行的程序,只需要在内存中有一份代码即可。另外,代码区还规划了局部变量的相关信息。

数据段:用来存放存放程序中明确被初始化的全局变量、静态变量(包括全局静态变量和局部静态变量)和常量数据(如字符串常量)。另外,如果在函数名前加上static,则表示此函数只能在当前文件中被调用。

BSS段(uninitialized data segment)包含了程序中未初始化的全局变量,在内存中 bss段全部置零。

(heap):用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。一般由程序员分配和释放。分配方式倒是类似于链表,当系统收到程序的申请时,会遍历记录空闲内存地址的链表,以求寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲 结点链表中删除,并将该结点的空间分配给程序。

(stack):由编译器自动分配释放,存放函数的参数、返回值、临时创建的局部变量,以及在进行任务切换时存放当前任务的上下文内容。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把栈看成一个寄存、交换临时数据的内存区。

为什么要这么分配内存?

(1)一个进程在运行过程中,代码是根据流程依次执行的,只需要访问一次,当然跳转和递归有可能使代码执行多次,而数据一般都需要访问多次,因此单独开辟空间以方便访问和节约空间。

(2)临时数据及需要再次使用的代码在运行时放入栈区中,生命周期短。

(3)全局数据和静态数据有可能在整个程序执行过程中都需要访问,因此单独存储管理。

(4)堆区由用户自由分配,以便管理。

内存的分配方式

在C语言中,对象可以使用静态或动态的方式分配内存空间。

静态分配:编译器在处理程序源代码时分配。

动态分配:程序在执行时调用malloc库函数申请分配。

静态内存分配是在程序执行之前进行的因而效率比较高,而动态内存分配则可以灵活的处理未知数目的。

静态与动态内存分配的主要区别如下:

静态对象是有名字的变量,可以直接对其进行操作;动态对象是没有名字的一段地址,需要通过指针间接地对它进行操作。

静态对象的分配与释放由编译器自动处理;动态对象的分配与释放必须由程序员显式地管理,它通过malloc()和free两个函数来完成。

堆区动态内存管理

在编写程序时,通常并不知道需要处理的数据量,或者难以评估所需处理数据量的变动程度。在这种情况下,要达到有效的资源利用,必须在运行时动态地分配所需内存,并在使用完毕后尽早释放不需要的内存,这就是动态内存管理原理

动态内存管理同时还具有一个优点:当程序在具有更多内存的系统上需要处理更多数据时,不需要重写程序。标准库提供以下四个函数用于动态内存管理:

(1) malloc()、calloc()分配新的内存区域。
       函数void*malloc(size_t size)分配连续的内存区域,其大小不小于 size。当程序通过 malloc()获得内存区域时,内存中的内容尚未决定,需要再使用memset()初始化数据。

       函数 void*calloc(size_t count,size_t size)分配一块内存区域,其大小至少是 count_size。换句话说,上述语句分配的空间应足够容纳一个具有 count 个元素的数组,每个元素占用 size 个字节。而且,calloc()会把内存中每个字节都初始化为 0。
      两个函数都返回 void 指针,这种指针被称为无类型指针(typeless pointer)。返回指针的值是所分配内存区域中第一个字节的地址,当分配内存失败时,返回空指针。当程序将这个 void 指针赋值给不同类型的指针变量时,编译器会隐式地进行相应的类型转换。当获取所分配的内存位置时,所使用的指针类型决定了该如何翻译该位置的数据

(2) realloc()调整已分配的内存区域。

(3) free()释放已分配的内存区域。

上述所有函数都声明在头文件 stdlib.h 中。对象在内存中所占空间的大小是以字节为单位计算的。许多头文件(包括 stdlib.h)专门定义了类型 size_t 用来保存这种内存空间的相关信息。例如,sizeof 运算符以类型 size_t 返回字节数量。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值