详解动态开辟问题

 升起时奋斗,日落时自省

目录

一、常见的动态内存错误

  1.对NULL指针的解引用操作

2、对动态开辟之间的越界访问

3、对非动态开辟内存使用free释放

4、使用free释放一块动态开辟内存的一部分

5、对同一块动态内存多次释放

6、动态开辟内存忘记释放(内存泄漏)

二、内存开辟


一、常见的动态内存错误

  1.对NULL指针的解引用操作

#include<stdio.h>
#include<stdlib.h>


int main()   //错误  没有检测p是否开辟成功
{
    int* p = (int*)malloc(40);
    *p = 20;
    return 0;
}


int main()   //正确 
{
    int* p = (int*)malloc(40);
    if (p == NULL)
    {
        perror(p);
    }
    *p = 20;
    free(p);
    p = NULL;
    return 0;
}

 动态开辟内存,需判断是否为NULL,代码运行更可靠,动态开辟易产生内存泄漏,该情况也存在内存泄漏,没有在程序结束时,free掉原来开辟的内存。


2、对动态开辟之间的越界访问

#include<stdio.h>
#include<stdlib.h>
int main()
{
    int* p = (int*)malloc(40);
    if (p == NULL)
    {
        perror(p);
        return 1;
    }
    int i = 0;
    for (i = 0; i <= 10; i++)//越界访问
    {
        p[i] = i;
    }
    free(p);
    p = NULL;
    return 0;
}

当前开辟内存只有40个字节,但是在i在这里为11个int,相当于44个字节,越界访问


3、对非动态开辟内存使用free释放

void test()
{
    int a = 10;
    int* p = &a;
    free(p);
    p = NULL;
    return 0;
}

非动态开辟free会直接报错


4、使用free释放一块动态开辟内存的一部分

int main()
{
    int i = 0;
    int* p = (int*)malloc(10*sizeof(int));
    if (p == NULL)
    {
        perror(p);
        return 1;
    }
    for (i = 0; i < 10; i++)
    {
        *p = i; 
        p++;   //这里改变了p的位置
    }
    free(p);  //不能释放部分p内存
    p = NULL;
    return 0;
}

 当前p的变化如上图,free是p以后的内存,这是不能的,在上面的错误代码中p直接走到了最后当前如果free要进行的话,又什么都free不了。

更改:p++改为*(p+i);


5、对同一块动态内存多次释放

int main()
{
    int* p = (int*)malloc(40);

//...
    free(p);
//...
    free(p);
}

当前p内存以及释放一次,在次释放,系统也不知道做什么,就会报错,在每次free之后记得将其置空p=NULL,再次释放也不会有太大的影响


6、动态开辟内存忘记释放(内存泄漏)

#include<stdio.h>
#include<stdlib.h>

void test()
{
    int* p = (int*)malloc(10 * sizeof(int));

    int flag = 0;

    //...
    scanf("%d", &flag);
    if (flag == 5) //如果当前执行了,那就没有机会free
        return;
    //...
    free(p);
    p = NULL;
}
int main()
{
    test();
    return 0;
}

 

int *test()
{
    int* p = (int*)malloc(10 * sizeof(int));

    if(p=NULL)
    {
        return p;
    }
    return p;
}
int main()
{
    int *ret=test();

    return 0;
}

第一种,在代码中途以及return返回了,不能执行free释放空间,导致内存泄漏

第二种,是忘记了,在调用函数中申请的内存,返回时忘记了在主函数中释放内存

内存泄漏:是当前开辟内存,你用完后,又不释放掉,那就相当于没有人再去使用这块内存,就是内存泄漏 


二、内存开辟

 堆区(Heap) :运行时分配、手动开辟、释放内存

栈区 (Stack):局部变量、运行时分配、系统自动管理 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值