我们已经掌握的内存开辟方式有:

  1. int val=20;//在栈空间上开辟四个字节
  2. char arr[10]={0};//在栈空间上开辟10个字节连续空间

但是上述的开辟空间方式有2个特点

1.空间开辟大小固定

2.数组在声明的时候,必须指定数组长度,它所需要的内存在编译时分配

但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道,那数组的编译时开辟空间的方式就不能满足了。这时候就要尝试开辟动态内存

malloc,calloc,realloc和free这4个函数

·malloc

  1. void * malloc(size_t size);

这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针。

1.如果开辟成功,则返回一个指向开辟好空间的指针。

2.如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。

3.返回值的类型时void *,所以malloc函数并不知道开辟空间类型,具体在使用的时候使用者自己来决定。

4.如果参数size为0,malloc的行为是标准是未定义的,取决于编辑器。

举个列子

  1. //内存申请10个整形空间
  2. int *p = (int *)malloc(10 * sizeof(int));
  3. if (p==NULL)
  4. {
  5. //打印错误
  6. printf("%s", strerror(errno));
  7. }
  8. else
  9. {
  10. for (size_t i = 0; i < 10; i++)
  11. {
  12. *(p + i) = i;
  13. printf("%d\r\n", *(p + i));
  14. }
  15. }

·free 

  1. void free(void * ptr);

free函数专门用来做动态内存释放和回收的

1.参数ptr指向的空间不是动态开辟的,那free函数的行为是未定义的

2.参数prt是NULL指针,则函数什么事都不做。

举个例子

  1. //内存申请10个整形空间
  2. int *p = (int *)malloc(10 * sizeof(int));
  3. if (p==NULL)
  4. {
  5. //打印错误
  6. printf("%s", strerror(errno));
  7. }
  8. else
  9. {
  10. for (size_t i = 0; i < 10; i++)
  11. {
  12. *(p + i) = i;
  13. printf("%d\r\n", *(p + i));
  14. }
  15. }
  16. //当动态申请空间不在使用,应该还给操作系统
  17. free(p);

但是实际上free(p)后的指针依然指向这些内存防止误操作和内存泄漏这些内存应该让p置空

  1. //内存申请10个整形空间
  2. int *p = (int *)malloc(10 * sizeof(int));
  3. if (p==NULL)
  4. {
  5. //打印错误
  6. printf("%s", strerror(errno));
  7. }
  8. else
  9. {
  10. for (size_t i = 0; i < 10; i++)
  11. {
  12. *(p + i) = i;
  13. printf("%d\r\n", *(p + i));
  14. }
  15. }
  16. //当动态申请空间不在使用,应该还给操作系统
  17. free(p);
  18. p=NULL;//置空

·calloc

  1. void * calloc(size_t num,size_t size);

1.函数功能是为num个大小为size的元素开辟一块空间,并且把空间的每个字节初始化为0;

2.与函数malloc的区别只在于calloc会在返回地址之前把申请的空间每个字节初始化为0

例如

  1. int *p = (int *)calloc(10 , sizeof(int));
  2. if (p==NULL)
  3. {
  4. //打印错误
  5. printf("%s", strerror(errno));
  6. }
  7. else
  8. {
  9. for (size_t i = 0; i < 10; i++)
  10. {
  11. //*(p + i) = i;
  12. printf("%d\r\n", *(p + i));
  13. }
  14. }

malloc 效率高一点但是不初始化 和calloc各有千秋。

·realloc

  1. void * realloc(void * ptr, size_t size);

1.realloc函数的出现让内存管理更加灵活

2.有时候我们发现过去申请的空间太小了,有时候我们又觉得申请的空间过大了,为了合理的管理内存

对他们做调整,realloc函数客园做到对动态开辟内存大小做调整

3.ptr要调整的内存地址

4.size调整之后新大小

5.返回值为调整后的内存起始位置

6.这个函数原内存空间大小基础上,还会将原来内存中的数据移动到新的空间(改变地址)

7.realloc 在调整内存空间存在2种情况

  7.1 原有空间足够大 不需要重新开辟直接在原有基础减少就好了

  7.2 原有空间足够大 需要重新开辟把原先存在的值复制到新的地址中

  1. int *p = (int *)calloc(5 , sizeof(int));
  2. if (p==NULL)
  3. {
  4. //打印错误
  5. printf("%s", strerror(errno));
  6. }
  7. else
  8. {
  9. for (size_t i = 0; i < 5; i++)
  10. {
  11. *(p + i) = i;
  12. }
  13. //申请40个空间
  14. int *p2 = (int *)realloc(p, 40);
  15. for (size_t i = 5; i < 10; i++)
  16. {
  17. *(p + i) = i;
  18. }
  19. for (size_t i = 0; i < 10; i++)
  20. {
  21. printf("%d\r\n", *(p + i));
  22. }
  23. }
  24. //当动态申请空间不在使用,应该还给操作系统
  25. free(p);

当我们申请空间较小时运行可以看到

 

 

 2个地址相同 代码没什么

可以看到返回新地址了 它在后面地址地址不够后 会选择重新开辟空间

1.对NULL指针解引用操作

  1. void test()
  2. {
  3. int *p = (int *)malloc(10 * sizeof(INT_MAX));
  4. *p = 20;//如果p的值是NULL,就会有问题
  5. free(p);
  6. }

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

  1. void test()
  2. {
  3. int *p = (int *)malloc(10 * sizeof(int));
  4. *p = 20;//如果p的值是NULL,就会有问题
  5. if (p == NULL)
  6. {
  7. //打印错误
  8. printf("%s", strerror(errno));
  9. }
  10. for (size_t i = 0; i <=10; i++)
  11. {
  12. *(p + i) = i;//当等于10就会存在越界
  13. }
  14. free(p);
  15. }

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

  1. void test()
  2. {
  3. int a = 10;
  4. int *p = &a;
  5. free(p);
  6. }

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

  1. void test()
  2. {
  3. int *p = (int *)malloc(10 * sizeof(int));
  4. p++;
  5. free(p);//p不再指向动态内存的起始位置
  6. }

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

  1. int *p = (int *)malloc(10 * sizeof(int));
  2. *p = 20;//如果p的值是NULL,就会有问题
  3. if (p == NULL)
  4. {
  5. //打印错误
  6. printf("%s", strerror(errno));
  7. }
  8. free(p);
  9. p = NULL;
  10. free(p);

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

  1. while(1)
  2. {
  3. malloc(1);
  4. sleep(1000);
  5. }

 

版权声明:本文为feizianquan原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/feizianquan/p/14659793.html