动态内存开辟和常见问题

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


一、动态内存开辟的函数有哪些呢?

malloc

1.void* malloc (size_t size);首先是参数部分,它需要你输入你需要开辟的字节个数并且无符号数,然后它的返回类型,如果开辟成功它会返回开辟成功的第一个元素地址(这里需要注意到返回类型是void*,所以一般都是需要强制类型转换的,强制类型转换的意思是,让编译器认为这是一个什么样的数据(编译器会按照强制类型转化后的数据类型进行读取)),如果开辟失败,它会返回NULL,开辟成功则会返回一个指向开辟好空间的指针,该函数是不会初始化它所开辟的空间的。

calloc

2. void* calloc (size_t num, size_t size),首先参数部分,size_t num,表示要开辟的元素个数,这个位置和mallco函数有很大的区别,因为malloc函数输入的字节个数,size_t  size表示需要开辟的数据类型的大小,一般用sizeof(数据类型)计算。如果开辟成功,返回一个指向开辟好的空间的指针,这个函数和malloc不一样的地方不仅仅是参数,还有它会把成功开辟的空间进行初始化为0,如果开辟失败也会返回NUll。

realloc

3.void* realloc (void* ptr, size_t size),该函数的目的是为了调整目前开辟的空间大小,参数部分第一个参数,需要输入你已经开辟好的一个空间的地址(当然也可以是NULL),然后size_t size 是你需要调整为多大的空间需输入字节个数,它的返回地址最好使用一个临时的指针变量来接收因为如果这个函数如果发现你需要开辟的空间后面空间不够,它会重新寻找一符合需要大小的块空间来作为现在开辟的空间,并将它的地址进行返回,还有就是为了避免返回NULL带来的影响,如果参数部分void*ptr是NULL,它的功能就和malloc函数是一样的,返回一个指向size个字节的空间的指针。

free

4.void free (void* ptr),该函数就是为了释放过开辟的空间,参数就是开辟空间的首元素地址这个一定是首元素地址其他地址都是不行的,程序会崩溃,这个函数一般是和malloc,calloc,realloc成对出现,有开辟就有回收嘛。当然也避免产生内存泄漏,如果参数是NULL,那就什么事都不做。

二、常见错误

1.对NUll解引用

代码如下(示例):


void test1()
{
      int*p=(int*)malloc(INT_MAX);//INT_MAX表示有符号数整数类型的最大值
        *p=20;//这里如果返回的是NULL,这里程序就会崩溃
        free(p);
         p=NULL:
}

 程序会崩溃,所以一般使用的时候要判断一下,或者是断言一下。

 

2.对动态开辟空间越界访问

代码如下(示例):

void test2()
{
    int *p=(int*)malloc(40);//开辟40个字节的空间
    assert(p);//防止p为空指针
    int i=0;
    for(i=0;i<40;i++)
    {
        *(p+i)=i;//该位置会形成越界访问
           //因为我们已经将它强制类型转化为int*行的数据,
           //所以40应该改为10
    }
      free(p);
}

程序虽然会看似正常运行,但是已经形成了越界访问。 

 

3.对非动态内存空间进行free

void test3()
{
    int a=0;
    int*p=&a;
    free(p);//此位置是有问题的,我们关于开辟和释放的内存问题一直是堆上的
    p=NULL;  //然而这个a,是栈上的,最后的结果就是编译器也不知道怎么办
}

4.使用free释放了一部分内存

 

void   test()
{
    int *p=(int*)malloc(40);
    assert(p);
    int i=0;
    for(i=0;i<5;i++)
      {
        *p=i;
          p++;/从这里开始,p已经不指向首元素地址了
      }
    free(p);//p的地址已经发生了变化已经不再是指向开辟地址的首位置了
      p=NULL;      //程序到这个位置直接会崩掉,因为我们需要起始地址
}

5.对同一块内存多次释放

 

void test4()
{
    int *p=(int*)malloc(40);
       assert(p);
       int i=0;
    for(i=0;i<10;i++)
    {
        *(p+i)=i;
    }
        free(p);//该位置已经把这块内存还给了操作系统,
                //往后的p已经是野指针了,而且没有制为空,
                //所以往后通过p还是可以找到这块内存
        //


        //
        free(p);//这个位置是野指针会被报错
                //如果前面已经置为空这个位置就没有问题会直接跑过去,因为free对与空指针
                //没有任何操作
        p=NULL;

}

6.忘记释放造成内存泄漏

void test()
{
   int *p=(int*)malloc(40);
    assert(p);
    *p=20;
     while(1); //p所开辟的内存空间一直都不到释放会造成吃内存现象
  
}

像这样吃内存是非常吓人的,在那么一瞬间电脑就直接接近死机。

总结

 对与动态内存的使用,需要记住开辟时强制类型转换,断言(判断)防止开辟不成功,使用完记得free,之后记得置为空指针,对于realloc这个函数不要用一开始开辟空间的指针去接收它避免开辟失败后所带来的空指针被它接收,造成得不偿失。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值