内存碎片与内存泄漏

内存碎片:

什么是内存碎片:

已经释放了使用的权的内存,但无法被malloc再次分配出去,这种内存叫内存碎片。

int* p1 = malloc(4);
int* p2 = malloc(4);
int* p3 = malloc(4);
​
free(p2);
​
// 此时p2已经被释放,但无法再次分配给p4,p2就是内存碎片,如果后续不再分配较小的内存块,p2可能一直接内存碎片
int* p4 = malloc(16);
​
// 此时p2就有可能被再次分配出来,它就不是内存碎片,
int* p5 = malloc(4);
​
// 如果p1或p3被释放,p2就不是内存碎片了
free(p1);
free(p3);

内存碎片产生的原因:

内存和释放、分配时间、大小不协调导致的。

一块内存碎片,只是短时间内是碎片,过一段时间它可能就不是碎片了,所以内存碎片不是绝对的。

如何减少内存碎片:

前提:内存碎片只能尽量减少,无法杜绝。

1、尽量使用栈内存(要了解栈内存的特性,要知道栈内存的使用上限,ulimit -s 、ulimit -s <size>)。

2、尽量分配大块内存自己管理。

int* p1 = malloc(16);
int* p2 = p1+1;
int* p3 = p1+2;
int* p4 = p1+3;

3、按照分配的顺序,逆序释放,把堆内存当栈进行管理。

int* p1 = malloc(4);
int* p2 = malloc(4);
int* p3 = malloc(4);
int* p4 = malloc(4);
​
free(p4);
free(p3);
free(p2);
free(p1);

4、内存碎片整理

int* p1 = malloc(4);
int* p2 = malloc(4);
int* p3 = malloc(4);
​
memcpy(p2,p3,4);
swap(p2,p3);
free(p2);

内存泄漏:

什么是内存泄漏:

内存已经不再使用,但无法被释放的内存叫内存泄漏。

但这不是最严重的,严重的是反复的内存泄漏,例如:一个函数执行需要分配一块堆内存,等它执行完毕后堆内存没有被释放,等再次调用这个函数时,它又重新分配堆内存,又没有释放,反复这样会导致可用的内存越来越少,系统、程序会变得越来越慢、卡、死机。

void func(void)
{
    int* p = malloc(40);
    for(int i=0; i<10; i++)
    {
        p[i] = rand() % 100;
        printf("%d ",p[i]);
        if(条件)
            return;
    }
    printf("\n");
    free(p);
}
​
int main()
{
    for(;;)
    {
        ...
        func();
        ...
    }
}

产生内存泄漏的原因:

1、只写的内存分配语句,而忘记写内存释放语句,可能是粗心大意,也可能是以为别人会释放。

2、写了内存释放语句,但由于执行流程、执行条件设计有问题,导致释放语句没有执行。

3、与堆内存配合的指针被破坏,改变了指向,导致free语句执行无效。

如何减少内存泄漏:

1、按规则分配、释放内存:

自用:谁申请谁释放,分配语句和释放语句成对出现。

共用:谁知道该释放谁释放,项目组中负责分配和负责释放的人要进行对接。

2、封装malloc和free函数,记录每一次的分配和释放的内存块地址,通过对比记录,就可以发现是否有内存泄漏。

void my_free(void* ptr)
{
    printf("free %p\n",ptr);
    free(ptr);
}
​
void* my_malloc(size_t size)
{
    void* ptr = malloc(size);
    printf("malloc %p\n",ptr);
    return ptr;
}

3、使用const保护与堆内存配合的指针变量,防止指针被破坏。

int* const p = malloc(4);
​
p = &num; // 编译会出错
​
free(p); // 此时释放的肯定是堆内存

检查内存泄漏的工具:

# 安装该工具的命令
sudo apt install valgrind
​

#使用该工具检测程序:
valgrind --tool=memcheck --leak-check=yes ./a.out

内存泄漏和内存碎片的危害:

前提:当程序结束时,操作系统会把分配它的所有资源全部回收(包括系统分配给程序的堆内存),所以当程序结束时,内存碎片和内存泄漏就会消失,这也是为什么软件、系统重启能解决很多问题。

注意:服务器端的程序一般需要7*24小时运行,不能随意结束。

客户端的程序可以随意的关闭、重启系统和软件,所以即使发生内存碎片和内存泄漏,也问题不大,但如果是服务端的程序,即使只有少量的内存泄漏和内存碎片,长年累月下来也会导致系统可用的内存越来越少,系统、程序会变得越来越慢、卡、死机。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值