关于动态内存(C)

  提到动态内存,我们一定会想到 malloccallocrealloc 这三巨头开辟动态内存的函数。

  我们先来认识一下这三个函数吧:

  ①malloc: void* malloc(size_t size (字节数))  ,开辟 size_size 字节的空间,但并不会对开辟的空间进行初始化。若开辟失败,则返回空指针(NULL)。 

  ②calloc:void* calloc(size_t num(个数) , size_t 大小),为num个元素分配一块内存,每个元素所占空间大小为size_t,开辟成功后,将所有位初始化为零。

  ③realloc:void* realloc(void* p,size_t size (字节数)),更改p指向的内存大小,指向的内存大小为 size_t size ,若在 指针p 这里可以开辟 size_t size 字节的空间,那么将在原有的空间后拓展空间,若不行,那么将会另辟蹊径,寻找一块可以开辟 size_t size 字节的空间,并将p指向这个空间的起始位置的同时,将原先的数据复制过来。(若p是NULL,那么,将会与 malloc 函数作业一样)。

  众所周知,动态内存是存放在堆区的,相较于开辟在静态区和栈区的空间,动态内存是更为灵活的,因为开辟的空间是通过指针指向起始位置来使用的,这就意味着我们可以在合理的范围内,随意改变这块内存空间的大小。

  但是!"天下没有免费的午餐",既然我们可以随意的调整这一块内存空间,那么这一块内存空间当然也需要我们亲自释放 ——— 还给操作系统。上一段落我们提到,使用动态内存需要一个指向动态内存的指针,这也就说明,在我们释放完动态内存之后,我们还需要将这个原指向动态内存的指针不再指向这一块空间,因为这一部分的空间已经不能通过这个指针去使用了。做个通俗的比喻,这就好像我们去住酒店一样,开好房间、拿到房卡,到了退房的时候,我们不仅要把自己的东西拿走,把房间还给酒店,还需要将能打开这个房间的房卡还给酒店在这个比喻中,房卡就代表着指针。因此,我们在释放指针指向的空间 ( free(p) ) 之后,还需要将指针置为空值                       ( p = NULL )。

  综上所述,我们在使用动态内存时就要多加小心了。

  让我们来列举一下常见的错误,看看你有没有中招喔!

void test()
{
  int *p = (int *)malloc(INT_MAX/4);
  *p = 20;
  free(p);
  p = NULL;
}

  Q:可能有的人会说,这段代码,p指向的空间释放了,p也置为空指针了,没问题啊!

  A:请注意,上述考虑的是动态内存开辟好后的做法,那如果动态内存都没有开辟呢?如果使用这个malloc函数压根就没有开辟空间,返回给指针 P 的是个空值,那么再对 P 进行释放( free )可就是个错误了!

  注意:所以我们在开辟动态内存后,最好要用 if 进行判断,当不为NULL时再进行后续操作。

  ②

void test()
{
  int i = 0;
  int *q = (int *)malloc(10*sizeof(int));
  if(NULL == q)
  {
    exit(EXIT_FAILURE);
  }
  for(i=0; i<=10; i++)
  {
    *(q+i) = i;
  }
  free(q);
}

  这个代码我想大家都能看出来是什么问题吧,这个在不用动态内存时都会出现的错误 —— 越界访问。

  ③

void test()
{
  int *p = (int *)malloc(100);
  if(p != NULL)
  {
    p++;
    free(p);
    p = NULL:
  }
}

  Q:上述代码,开辟一个动态内存空间,将地址赋给指针p,判断动态内存是否成功开辟,成功开辟后进行操作,然后释放,将指针置为NULL,没有问题啊!!(是否有很多问号??)

  A:按照步骤来说,这个代码没有问题,首先,开辟空间、然后判断空间是否开辟成功、最后释放空间并将指向空间的指针置为空。但是我们仔细看一下就会发现,这个指向动态内存的指针p的值发生了变化!p++了,所以p并不是指向整个动态内存,因此我们也仅仅只是对部分的空间进行了释放等操作。

  注意:因此,我们一定要看清楚指向动态内存的指针变量是否发生改变,最好不要让这个指针进行自增,如果非要自增的话,可以创建一个临时变量。

  以上,就是动态内存的一些注意事项,有收获的朋友点个赞再走!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值