C语言之堆内存管理

堆内存管理

为什么使用堆内存

  1. 栈内存的大小是有限的(堆内存的大小受物理内存限制)。
  2. 栈内存中的数据释放是不受程序员控制的(函数结束后,属于它的栈内存就会被系统自动释放,它不适合长期存放数据)。

如何使用堆内存

  1. 堆内存无法与标识符建立对应关系(必须使用指针来指向堆内存)
  2. c语言中没有管理堆内存的语句(标准库提供了一套函数来管理堆内存)
  3. 堆内存的管理和释放由程序员手动操作(显式调用函数来管理)

C语言为内存的分配和管理提供了几个函数。这些函数可以在<stdlib.h>头文件中找到。

函数描述
mallocvoid* malloc(size_t size);
功能:在堆区分配一块指定大小的内存空间,用来存放数据。
size:要申请的字节数
返回值:所申请到内存的首字节地址,需要使用指针来接收(如果size的值为0,则返回NULL)
注意:这块内存空间在函数执行完成后不会被初始化,它们的值是未知的。
freevoid free(void* address);
功能:释放内存空间,只是把内存的使用权收回,部分内容还在(只象征性的破坏了内容开头的一部分)。
address:malloc的返回值,之前所申请的堆内存的首地址。
注意:1、内存释放后还能再继续访问(不产生段错误,可能会造成脏数据),但是在非法使用。2、内存释放后,指针要立即置空,否则指针就会成为野指针。3、一块内存不能连续释放两次,会出现堆奔溃。
callocvoid* calloc(size_t num, size_t size);
在内存中分配了 num*size 个字节长度的内存空间,并且每个字节的值都是0。
num:申请的次数
size:每次申请的字节数
返回值:所申请的内存的首地址。如果size或num为0,返回NULL。
注意:calloc的速度会比malloc慢,因此绝大数情况下不使用。
reallocvoid* realloc(void* address, size_t size);
功能:调整已经申请到的内存的大小。(相当于拷贝了一块新内存,旧内存会被释放掉)。
address:内存的首地址。如果address为空,而size大于0,则相当于申请新内存。
size:把内存大小调整为size。如果address不为空,而size为0,则相当于释放内存。
返回值:调整后的内存的首地址,一定要重新接受,旧地址已经被释放。
#include <stdio.h>
#include <stdlib.h>
int main()
{
	// 从堆内存申请1个字节
	int* p1 = malloc(1);
	// 从1字节调整为4字节
	realloc(p1,4);
	// 从4字节调整为2字节
	realloc(p1,2);
	// 从堆内存申请4字节
	int* p2 = realloc(NULL,4);
	// 释放内存
	realloc(p2,0);
	// 释放内存后要将指针置空
	p2 = NULL;
}

要想进行内存的初始化,可以使用以下函数:

函数描述
bzerovoid bzero(void* s, size_t n);
头文件:<strings.h>
功能:把一块内存的所有字节设置为0(清理内存)
s:要清理的内存的首地址
n:要清理的字节数
memsetvoid *memset(void *s, int c, size_t n);
头文件:<string.h>
功能:把一块内存的每一个字节都设置为c
s:要清理的内存的首地址
c:字节中要设置的数据(-128~127)
n:要设置的字节数
返回值:初始化后的内存首地址(方便链式调用)。

注意: void* 是一种无类型的指针

  1. 不能直接使用,不能通过这种指针变量解引用(必须先转为其他类型)
  2. 可以和任意类型的指针进行自动转换。
  3. void* 也叫万能指针,解决函数之间专递指针参数时类型不确定问题。
  4. GNU 认为 void* 和 char* 一样

使用堆内存要注意的问题

当程序结束时,属于它的资源都会被操作系统回收。

  1. 内存泄露:由于失误而忘记或无法释放堆内存,导致堆内存无法循环利用,从而每次都重新申请新的内存,可用的内存会越来越少。

    • 如何定位内存泄露:
      1. 当程序运行后观察内存的使用情况,内存暴涨则检查循环中的申请内存。
      2. 检查在调用free前指针是否已经变成空指针。
      3. 检查条件、业务逻辑,保证free会被调用。
    • 解决方法:
      1. 保护指针不被修改,使用const修饰堆内存的地址
      2. 每一个malloc必须有对应的free。
  2. **内存碎片:**已经被释放但不能被再次分配使用的内存。频繁的申请、释放内存,导致申请和释放的不协调,一部分内存无法被再次使用。内存碎片无法杜绝,只能尽量减少。

    • 如何减少:
      1、尽量少使用堆内存,栈内存可以解决的尽量使用栈内存。
      2、尽量申请大块的内存。
      3、不要频繁的申请和释放。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值