动态内存管理

简介: 动态内存管理

一、什么是动态内存管理?

      一种内存管理方法。对内存空间的分配、回收等操作在进程执行过程中进行,以便更好地适应系统的动态需求,提高内存利用率


二、为什么需要动态内存管理?

    对于初学者而言,已经基本可以掌握的内存开辟方法:定义+初始化的方法。

  int a=0; int arr[]={0,1,2,3}

  char arr[]={"abcd"}等等

  但是上述内存的开辟大小是在编译前就确定的,同时数组在声明的时候又必须指定数组长度,    它所需要的内存在编译的时候分配;【这种开辟方式的特点

  但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道, 那数组的编译时开辟空间的方式就不能满足了,而且盲目的开辟内存只会造成内存的浪费

              【这时候就只能试试动态存开辟了】


三、动态内存函数

 1、malloc

定义  : void* malloc (size_t size);  (stdlib.h)


  作用

      向内存申请一段连续的、可用的空间

  特点

 //返回类型为void*,参数为开辟空间的大小(单位字节)


  1. 这个函数向内存申请一段连续可用的空间,并返回指向这个空间的指针
  2. 如果开辟成功,则返回一个指向开辟好空间的指针。
  3. 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查(assert)。
  4. 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己 来强制类型转换。
  5. 如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。


  实例

运行结果为0 1 2 3 4

 
#include<stdio.h>
#include<stdlib.h>
int main()
{
    int* p = (int*)malloc(5 * sizeof(int));
    for (int i = 0;i < 5;i++)
    {
        *(p + i) = i;
        printf("%d ", *(p + i));
    }
    free(p);
    p = NULL;
    return 0;
}


 2、free

定义void free(void*str);(stdlib.h)

  作用

  free是c语言提供的,专门用来释放、回收动态开辟出来的空间的函数。


  特点

  1. 如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的,运行代码的时候将会报错
  2. 如果参数 ptr NULL指针,则使用free函数将什么事都不不会发生。

    (举例同上malloc实例)


 3、calloc

定义 void*calloc(size_t num,size_t size)

    (stdlib.h)

  作用

它的作用同malloc相似,也是向内存申请一段连续的、可用的空间。


  特点

  1. 函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0
  2. 与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0


  举例

#include<stdio.h>
#include<stdlib.h>
int main()
{
    int* p = (int*)malloc(5 * sizeof(int));
    printf("p(malloc):");
    for (int i = 0;i < 5;i++)
    {
        printf("%d ", *(p + i));
    }printf("\n\n");
    int* c = (int*)calloc(5, sizeof(int));
    printf("c(calloc):");
 
    for (int i = 0;i < 5;i++)
    {
        printf("%d ", *(c + i));
    }
    printf("\n\n");
    free(p);free(c);
    p = NULL;c=NULL;
    return 0;
}


4、realloc

void*reallocvoid*,size_t size) stdlib,h

  作用

  重新调整已开辟空间的大小。


realloc函数的出现让动态内存管理更加灵活。在使用malloc或者calloc函数的时候,可能会遇到动态开辟的内存仍然不够的情况,会觉得申请的空间过大或者过小,那为了合理地使用内存,避免再去重新开辟一段内存空间,造成难以维护的情况,那么将会使用到realloc函数。 realloc 函数就可以做到对动态开辟内存大小的调整。


  特点

  1. 指针p是要调整的已经开辟的空间的地址
  2. size是调整后的大小(单位:字节)
  3. 这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到的空间。
  4. 在使用realloc调整动态内存的时候存在两种不同的开辟方法:


   方法1、原有空间之后存在足够的且连续的空间:

   方法2、在堆空间中另找一块连续的空间;

 情况 1

当是情况 1 的时候,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化。

 情况 2

当是情况 2 的时候,原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小


的连续空间来使用。这样函数返回的是一个新的内存地址。

  实例

1.   int*p=(int*)malloc(5*sizeof(int));
2. //若空间不够了,使用realloc
3. int*p=(int*)realloc(p,10*sizeof(int));

四、常见动态内存错误

 1、动态内存访问越界

类似于数组int arr[10]访问越界:访问了不属于它的空间。

int arr[10];   arr[11]=0;


动态内存开辟的空间同样存在越界访问的问题

案例

 

int i = 0;
    int* p = (int*)malloc(10 * sizeof(int));
    if (NULL == p)
    {
        exit(EXIT_FAILURE);
    }
    for (i = 0; i <= 10; i++)
    {
        *(p + i) = i;//当i是10的时候越界访问
    }
    free(p);
    p = NULL;


 2、对NULL空指针进行解引用操作

int * p = ( int * )  malloc ( INT_MAX / 4 );

* p = 20 ; //如果malloc开辟空间失败,则会返回空指针(NULL),此时将空指针赋给p

//解引用后就是对空指针的解引用

这种操作会引起程序或者系统崩溃

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

int a=10;   int*p=&a;  free(p);

此操作会引起程序崩溃;

 4、free未释放动态开辟的内存

      1、未使用free函数

这种错误较为隐蔽,错误产生了但是不容易被发现

int *p=(int*)malloc (5*sizeof(int));//未使用free

未使用free不会报错,但是存在内存泄漏,影响程序的正常运行。


      2、使用了free函数,但只释放了部分内存

   int* p = (int*)malloc(5 * sizeof(int));

   p++;  //此处将p的地址向后挪了一位;

   free(p);

p=NULL;


  • 当p的所指向的位置向后移位的时候,free只释放了部分动态开辟内存,仍存在一部分内存没有被回收,也是内存泄漏的一种。 此时运行程序就会发生崩溃。


 5、对一块动态开辟内存进行多次释放

int *p=(int*)malloc (5*sizeof(int));  //假设开辟成功

free(p);

free(p);


同样会报错。

解释:当你将p  free释放的时候,p指向的这块空间已经不属于malloc等函数动态开辟的空间,系统可能将这块空间分配给了其他程序,这时在此使用free就相当于释放了非动态开辟内存,就会同上面一样报错。


总结

此文章讲解了什么是动态内存管理,以及一些常用的动态内存管理的函数,和常见错误

目录
相关文章
|
3月前
|
程序员 编译器 C语言
|
5月前
|
编译器 C语言
动态内存管理(1)
动态内存管理(1)
40 4
|
5月前
|
存储 Linux C语言
5.C++动态内存管理(超全)
5.C++动态内存管理(超全)
|
6月前
|
程序员 编译器 C语言
带你彻头彻尾了解『动态内存管理』
带你彻头彻尾了解『动态内存管理』
|
6月前
|
编译器 程序员 C语言
动态内存管理(超详细!)
动态内存管理(超详细!)
56 2
|
6月前
|
安全 C++ 开发者
c++动态内存管理(二)
c++动态内存管理(二)
138 0
|
6月前
|
程序员 C语言 C++
详解动态内存管理!
详解动态内存管理!
|
6月前
|
存储 安全 算法
c++动态内存管理(一)
C++ 动态内存管理 在 C++ 中,动态内存管理是一个核心概念,它允许在运行时分配和释放内存。以下是 C++ 动态内存管理需要掌握的关键知识点:
162 0
|
11月前
|
程序员 编译器 C语言
动态内存管理(2)
动态内存管理(2)
46 0