7-7 动态内存分配

1. malloc

        直接创建数组一般存储在函数调用栈上,而使用 malloc 分配内存从而进行存储的数据则是存放在堆区;堆区的数据与函数调用栈上的数据不同,堆区数据在函数释放后也不会释放内存,需要用 free() 主动释放

#include <stdio.h>
#include <stdlib.h>
#define PLAYER_COUNT 10

int main(){

  int *players = malloc(PLAYER_COUNT * sizeof(int));
  for (int i = 0; i < PLAYER_COUNT; ++i) {
    players[i] = i;
  }
  for (int i = 0; i < PLAYER_COUNT; ++i) {
    printf("%d ", players[i]);
  }
		  
  free(players);    // 释放内存

  return 0;
}

2. 函数参数应为二维指针

        free() 释放后的内存块对存在其中的值无影响,还会保留在内存块中,所以在调用 malloc 时,需要对新来的内存块上的值进行初始化操作(初始化操作中的二维指针,实质上就是在函数内部修改外部的指针变量,看自己那篇18年的博客,有详解)

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

#define PLAYER_COUNT 10

void InitPointer(int **ptr, int length, int default_value){
  *ptr = malloc(length * sizeof(int));
  for (int i = 0; i < length; ++i) {
    (*ptr)[i] = default_value;
  }
}

int main(){

  // 和向函数传递想要修改的参数值的情况相同,必须将变量的地址传入函数才能进行修改,此处就是指针变量的地址传入InitPointer函数,进而修改指针变量的值
  int *players;

  InitPointer(&players, PLAYER_COUNT, 2);

  for (int i = 0; i < PLAYER_COUNT * 2; ++i) {
    printf("%d ", players[i]);
  }

  free(players);

  return 0;
}

3. calloc

        函数 calloc 与 malloc 不同,calloc 返回的内存会自动被清为 0,相当于做了一个预处理工作,不用自己做

players = calloc(PLAYER_COUNT, sizeof(int));

4. realloc

        realloc 函数,对原先的内存(注意,是在原有的内存基础上进行分配的)进行重新分配并增加或减少部分内存(以旧换新的感觉),但注意,realloc 新加的内存不会做清空操作,里面的值不能确定

int *players;
InitPointer(&players, PLAYER_COUNT, 2);


// 函数 realloc 的用法
players = realloc(players, 4*sizeof(int));    // 重新分配四块内存
for (int i = 0; i < PLAYER_COUNT; ++i) {
  printf("%d ", players[i]);    // 2 2 2 2 -842150451 ... ,只能确定前四个值,后面的值无法确定,因为是在原有空间的基础上重新分配了四块内存
}

printf("\n");

players = realloc(players, PLAYER_COUNT * 2 * sizeof(int));  // 重新分配20块内存

for (int i = 0; i < PLAYER_COUNT * 2; ++i) {
  printf("%d ", players[i]);  // 2 2 2 2 -842150451 -842150451 -842150451 ... 后面一直都是 -842150451,这个数字是什么含义?
}

free(players);

5. 分配内存之后...

        内存分配可能会失败,所以在使用 malloc calloc realloc 函数后,需要判断指针是否分配到了内存

if(players){

  ...  // 指针指向的地方有内存才有意义

}else{

  ...

}

6. 注意事项

    常见指针使用错误:
        1)忘记在使用指针完毕后释放内存
        2)使用了已经释放的内存(指针指向的内存被释放,但是指针变量并没有被销毁,还是可以继续使用的,如果在 free() 后再次使用该指针变量,就是这种情况,这种指针就是野指针)
        3)使用了超出边界的内存(类似数组越界)
        4)改变了内存的指针,导致无法正常释放(一个指针变量指向一块内存,如果这时将指针变量的值修改,使其指向其他内存,那原有的那块内存就会无法正常释放,因为没有指针变量指向它)

    动态内存使用建议:
        1)避免修改指向已分配内存的指针(对应 4)
        2)对于 free() 后的指针主动置为 NULL(对应 2)
        3)避免将过多的指针指向动态分配的内存(一旦其中一个指针使用 free() 操作,其他指针根本不知道,其他指针就化为了野指针)
        4)动态内存遵从谁分配谁释放的原则

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值