动态内存管理

目录

重点:

(一)为什么动态内存分配

(二)动态内存分配函数介绍

 (三)常见动态内存的错误

1:对NULL指针解引用

2:对开辟的空间越界访问

3:对非动态开辟的内存free

4:使用frees释放申请空间的一部分

5:对同一块内存多次释放

6:申请内存忘记释放导致内内存泄露


重点:

.什么存在动态内存分配
.动态内存函数的介绍
.malloc
.free
.calloc
.realloc
.常见的动态内存错误

(一)为什么动态内存分配

 之前我们见过两种变量开辟空间的方式:

int a=10;
char arr[20]="Hello World!";

上述的两种开辟方式有两个特点;

                1:空间的大小是固定的

                2:数组在定义时必须指定数组的长度

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

(二)动态内存分配函数介绍

首先我们来看malloc函数,它的函数原型是:

void* malloc (size_t size);

这个函数会向操作系统申请一块连续可用的空间,并返回这块内存的地址

~如果开辟成功,返回这块内存的地址;

~如果开辟失败,返回NULL.

~返回类型是void*,所以malloc函数并不知道你要申请这块空间给什么样的数据类型使用,因此,

 在使用mallc函数的时候一定进行强制类型转换。

~函数参数size是你所要申请的空间的大小,以字节为单位。

举例:

#include<stdio.h>
#include<stdlib.h>
int main()
{
    int *p=(int *)malloc(sizeof(int)*10);//p指向了可以存放10个整型数据的空间
    return 0;
}

c语言也为我们提供了释放空间的函数fee,函数原型如下:

void free (void* ptr);

free函数是用来释放我们申请的空间的:

~参数ptr是指向申请的空间

~如果参数ptr指向不是动态申请的空间,那么free的行为是未定义的。

~如果参数ptr指向NULL那么free就不产生任何的效果。

举例:

#include <stdio.h>
int main()
{
 //代码1
 int num = 0;
 scanf("%d", &num);
 int arr[num] = {0};
 //代码2
 int* ptr = NULL;
 ptr = (int*)malloc(num*sizeof(int));
 if(NULL != ptr)//判断ptr指针是否为空
 {
 int i = 0;
 for(i=0; i<num; i++)
 {
 *(ptr+i) = 0;
 }
 }
 free(ptr);//释放ptr所指向的动态内存
 ptr = NULL;//是否有必要?
 return 0; 
}
v

我们用malloc申请的空间是没有被初始化的,c语言为我们提供了另外一个申请空间的函数calloc函数,函数原型如下:

void* calloc (size_t num, size_t size);

~函数的功能是为num个大小为size的元素开辟空间,并把这块空间初始化为0;

举例:

#include <stdio.h>
#include <stdlib.h>
int main()
{
 int *p = (int*)calloc(10, sizeof(int));
 if(NULL != p)
 {
 //使用空间
 }
 free(p);
 p=NULL;
 return 0;
}

 

所以当我们需要申请一块空间你并且需要对它初始化时,就要使用calloc函数

而在程序运行的过程中需要的空间可能会发生变化,所以c语言为我们提供了重新申请空间的函数

relloc。函数原型如下:

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

~ptr是需要调整空间的地址。

~size调整后的空间大小,字节为单位。

~返回值是调整后的空间的地址。

relloc在调整空间的时候有两种情况:

1:原来空间的后面有最够的空间进行调整,那么就会在原来的空间后面追加空间

2:原来空间的后面没有足够的空间进行调整,那么就开辟一块新的空间,把原来空间中间中内            容拷贝过来,返回新的空间的地址。

 (三)常见动态内存的错误

1:对NULL指针解引用

void test()
{
 int *p = (int *)malloc(INT_MAX/4);
 *p = 20;//如果p的值是NULL,就会有问题
 free(p);
}

2:对开辟的空间越界访问

void test()
{
 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);
}

3:对非动态开辟的内存free

void test()
{
 int a = 10;
 int *p = &a;
 free(p);//这里就会报错
}

4:使用frees释放申请空间的一部分

void test()
{
 int *p = (int *)malloc(100);
 p++;
 free(p);//p不再指向动态内存的起始位置
}

5:对同一块内存多次释放

void test()
{
 int *p = (int *)malloc(100);
 free(p);
 free(p);//重复释放
}

6:申请内存忘记释放导致内内存泄露

void test()
{
 int *p = (int *)malloc(100);
 if(NULL != p)
 {
 *p = 20;
 }
}
int main
{

    test();
    while(1);
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值