0%

C语言内存管理

REmote DIctionary Server(Redis)是一个由Salvatore Sanfilippo写的key-value存储系统。Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

一、内存区域划分

      以C语言为底层的编程语言(包括其本身),其内存区域大致可以分为5大区域:栈区、堆区、静态区(全局区)、常量区、代码区(也有说分为4大区域:栈区、堆区、静态存储区、代码区,不同的编译器划分可能不同)。其中,局部变量、函数形参、临时变量都是在栈上获得内存的,它们获取的方式都是由编译器自动执行的。对于堆内存,C标准函数库提供malloc、calloc、realloc及free函数来进行管理。

  1. 栈区:由编译器自动分配和释放,存放着函数的参数和局部变量。

  2. 堆区:由程序员手动进行分配和释放,如果程序员不释放这块内存内存将一直被占用,直到程序运行结束由系统自动收回,对于C语言由malloc、calloc、realloc进行分配,free进行释放。

  3. 全局区(静态区):存储全局变量和静态变量,程序结束后由系统统一释放。

  4. 常量区:存放常量字符串,程序结束后由系统统一释放。

  5. 代码区:存放程序的二进制代码,程序运行期间该区域数据不可被修改只可以被执行。

二、堆区内存管理

  1. malloc:void * malloc(size_t size);

    • 使用时必须包含头文件<stdlib.h><malloc.h>
    • 开辟一块size字节大小的连续内存
    • 函数返回值是一个指针,指向刚刚开辟的内存的首地址
      • 如果开辟内存失败则返回一个空指针NULL
    • 申请的内存空间不会初始化(即不知道内部值是多少)
    • 当内存不再使用时应使用free()函数将内存块释放或由系统自动回收
  2. calloc:void * calloc(size_t n, size_t size);

    • 使用时必须包含头文件<stdlib.h><malloc.h>
    • 在内存的动态存储区中分配n个长度为size字节大小的连续空间
    • 函数返回一个指向分配起始地址的指针
      • 如果分配不成功返回NULL
    • 申请的内存空间会初始化,每一位都初始化为0
    • 当内存不再使用时应使用free()函数将内存块释放或由系统自动回收
  3. realloc:void * realloc(void * mem_address, size_t newsize);

    • 使用时必须包含头文件<stdlib.h>或<malloc.h>
    • 为已有内存的变量重新分配newsize字节大小的内存
    • 分配时先判断当前的指针是否有足够的连续空间,如果有则扩大mem_address指向的地址,并且将mem_address返回
      • 如果空间不够则先按照newsize指定的大小分配空间,将原有数据拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域同时返回新分配的内存区域的首地址
      • 原来指针是自动释放,不需要使用free
    • 如果重新分配成功则返回指向被分配内存的指针
      • 如果分配不成功返回NULL
    • 重新分配的内存也不会初始化
    • 当内存不再使用时应使用free()函数将内存块释放或由系统自动回收
  4. free:void free(void *ptr);

    • 释放指针变量ptr在堆区上的内存空间,ptr是需要释放的内存的起始地址
    • free要与malloc、calloc、realloc成对使用以避免内存泄露

内存泄漏(Memory leak)是在计算机科学中,由于疏忽或错误造成程序未能释放已经不再使用的内存。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。

内存溢出(Out Of Memory,简称OOM)是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于能提供的最大内存。

野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的),指针变量在定义时如果未初始化,其值是随机的,指针变量的值是别的变量的地址,意味着指针指向了一个地址是不确定的变量,此时去解引用就是去访问了一个不确定的地址,所以结果是不可知的。

三、参考

  1. 参考一
  2. 参考二