【C语言】动态内存分配malloc,realloc等函数使用和常见错误(上)

简介: 【C语言】动态内存分配malloc,realloc等函数使用和常见错误(上)

本章重点:

介绍malloc ,calloc , realloc 等动态内存分配函数的使用方法与常见的动态内存错误,与讲解几道动态内存分配的笔试题


1. 为什么存在动态内存分配



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


以上的内存开辟空间都是在栈上开辟的,而栈区的空间有以下几个特点:


  1. 空间开辟大小是固定的。
  2. 数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配。
  3. 栈区由编译器自动分配释放,由操作系统自动管理,无须手动管理。
  4. 栈区上的内容只在函数范围内存在,当函数运行结束,这些内容也会自动被销毁。
  5. 栈区上的地址是由高到底的


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

补充:

  1. 动态内存分配的空间是在堆区上开辟的
  2. 栈区上放的是局部变量和函数的形式参数等
  3. 静态区上放的是全局变量与静态变量(static)


2. 动态内存函数



malloc 和 free


malloc和free是成双成对出现的

malloc和free都声明在 stdlib.h 头文件中。


C语言提供了一个动态内存开辟的函数


void* malloc (size_t size);(size_t无符号整形)


malloc 使用方法与注意事项:

  • malloc这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针。
  • 如果开辟成功,则返回一个指向开辟好空间的指针。
  • 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
  • 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使

用者自己来决定。

  • 如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。
  • 如果没有free回收空间,系统会到最后自动回收,但是中间如果有大量程序要执行,这一

块空间就一直占用着,(千万不要这样处理)不释放会产生内存碎片,小型程序可以不关注,但是在中大型程序上影响极其深刻


注意:申请的空间刚开始都放的是随机值,如果要参与运算,都要给一个初始值,否则运算的结果肯定是随机值


free函数用来释放动态开辟的内存。

void free (void* ptr);


free使用方法与注意事项:

  • 如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
  • 如果参数 ptr 是NULL指针,则函数什么事都不做。
  • 每次动态内存开辟后,都要记得释放该开辟的内存
  • 释放空间后该指针还是指向原来的地址,为防止后面使用这个危险指针,应该释放完后赋

个NULL


  • 使用案例


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
int main()
{
  //向内存申请10个整形的空间
  int* p = (int*)malloc(40);
  //如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
  if (p == NULL)
  {
    //查询那里错误
    printf("%s\n", strerror(errno));
  }
  //如果开辟成功,则返回一个指向开辟好空间的指针
  else
  {
    //正常使用空间
    int i = 0;
    for (i = 0; i < 10; i++)
    {
      *(p + i) = i;
    }
    for (i = 0; i < 10; i++)
    {
      printf("%d\n", *(p + i));
    }
  }
  //当动态申请的空间不再使用的时候
  //就应该还给操作系统
  free(p);
  p = NULL;
  //释放空间后p还是指向原来的地址,为防止后面使用这个危险指针,使用赋个NULL
  system("pause");
  return 0;
}


最终输出结果:

0

1

2

3

4

5

6

7

8

9


calloc


C语言还提供了一个函数叫 calloc , calloc 函数也用来动态内存分配。


void* calloc (size_t num, size_t size);


函数的功能与malloc相似

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

为0。

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

全0。


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
int main()
{
  //calloc 全部初始化为0
  int* p = (int*)calloc(5, sizeof(int));
  if (p == NULL)
  {
    查询那里错误
    printf("%s\n", strerror(errno));
  }
  else
  {
    //正常使用
      int i = 0;
    for (i = 0; i < 5; i++)
    {
    printf("%d\n", *(p + i));
    }
  }
  当动态申请的空间不再使用的时候
  就应该还给操作系统
  free(p);
  p = NULL;//释放空间后p还是指向原来的地址,为防止后面使用这个危险指针,使用赋个NULL
  system("pause");
  return 0;
}


最终输出结果:

0

0

0

0

0


所以我们对申请的内存空间的内容要求初始化,那么可以很方便的使用calloc函数来完成任务。


calloc 和 malloc 的对比:

  1. 参数不一样
  2. 都是在堆区上申请内存空间,但是malloc不初始化,calloc会初始化为0
  3. 如果要初始化,就使用calloc不需要初始化,就可以使用malloc
目录
相关文章
|
安全 C语言
C语言中的字符、字符串及内存操作函数详细讲解
通过这些函数的正确使用,可以有效管理字符串和内存操作,它们是C语言编程中不可或缺的工具。
639 15
|
存储 缓存 算法
【C语言】内存管理函数详细讲解
在C语言编程中,内存管理是至关重要的。动态内存分配函数允许程序在运行时请求和释放内存,这对于处理不确定大小的数据结构至关重要。以下是C语言内存管理函数的详细讲解,包括每个函数的功能、标准格式、示例代码、代码解释及其输出。
767 6
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
844 1
|
程序员 C语言 C++
【C语言基础】:动态内存管理(含经典笔试题分析)-2
【C语言基础】:动态内存管理(含经典笔试题分析)
|
程序员 编译器 C语言
【C语言基础】:动态内存管理(含经典笔试题分析)-1
【C语言基础】:动态内存管理(含经典笔试题分析)
|
Java 数据库连接 C语言
C语言进阶教程(内存分配常见问题分析)
C语言进阶教程(内存分配常见问题分析)
282 0
|
存储 缓存 算法
C语言内存问题详细分析之完善
C语言内存问题详细分析之完善
362 0
C语言内存问题详细分析之完善
|
存储 C语言
|
存储 程序员 C语言
C语言内存分析
<div class="cnblogs_code"> <pre><span style="font-size:14pt"><span style="color:#0000ff">程序一: char</span>*<span style="color:#000000"> toStr() { </span><span style="color:#0000ff">char</span
1589 0