第七章 动态内存申请

本文介绍了C语言中动态内存管理的概念,包括静态分配与动态分配的区别。详细讲解了动态分配函数malloc、free、calloc和realloc的使用方法,强调了内存泄漏问题及其解决策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

7.1 概述

7.2 静态分配、动态分配

7.3 动态分配函数

7.3.1 malloc函数

7.3.2 free函数

7.7.3 calloc函数

7.3.4 realloc函数(重新申请内存)

7.4 内存泄漏


7.1 概述

数据的长度是预先定义好的,在整个程序中固定不变,容量不能改变。但实际编程时往往会发生所需的内存空间取决于实际输入的数据,无法预先确定。

C语言提供了一些内存管理函数,可以按需动态的分配内存空间,也可把不再使用的内存空间回收再次利用。

7.2 静态分配、动态分配

1、静态分配

在程序编译或运行过程中,按事先规定的大小分配内存空间的分配方式:int a[10],

(1)必须事先知道所需空间的大小

(2)分配在栈区或全局变量区,一般以数组的形式

(3)按计划分配

2、动态分配

在程序运行过程中,根据需要的大小自由分配所需的空间,分配在堆区,一般使用特定的函数进行分配

7.3 动态分配函数

7.3.1 malloc函数

include<stdlib.h>

void* malloc(unsigned int size);

参数是无符号整形,返回值是void指针。

在内存的动态存储区(堆区)分配一块长度为size字节的连续区域,用来存放类型说明符指定的类型,分配的内存空间内容不确定,一般使用memset初始化。

注意:

(1)函数原型返回void*指针,使用时必须做相应的强制类型转换

char* p;

p = (char*)malloc(20); //强制类型转换,将申请的内存空间转换为存储字符类型数据的内存空间。

(2)调用malloc后一定要判断一下申请内存是否成功,如果成功,返回值是分配空间的起始地址,如果失败,返回值是NULL。

(3)如果多次malloc申请的内存,第一次和第二次申请的内存并不一定是连续的。

例如:

#include<stdio.h>

#include<stdlib.h>


int main()

{

int* p;

int i, n;

printf("请输入您要申请的int数组的元素个数\n");

scanf_s("%d", &n);

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

if (p == NULL)

{

printf("malloc error\n");

return 0;

}

for (i = 0; i < n; i++)

{

p[i] = i;

}

for (i = 0; i < n; i++)

{

printf("p[%d] = %d\n", i, p[i]);

}

free(p);

return 0;

}

请输入您要申请的int数组的元素个数

4

p[0] = 0

p[1] = 1

p[2] = 2

p[3] = 3

7.3.2 free函数

#include<stdlib.h>

void free(void *ptr)

free函数释放的是ptr指向的内存,而ptr指向的内存必须是malloc、calloc、relloc动态申请的内存。

注意:

(1)free后由于没有给p赋值,所以p还是指向原先动态申请的内存,但是内存已经不能再使用了,p变成野指针;

(2)同一块动态申请的内存不能多次free

7.7.3 calloc函数

#include<stdlib.h>

void calloc(size_t nmemb, size_t size);

有两个参数,size_t实际上是无符号整形,是在头文件中用typedef定义出来的,nmemb是申请的内存块数量,size是每块的字节大小,返回值是通用指针void*。

在内存的堆中,动态申请nmemb块,每块的大小都是size字节的连续区域。

注意:

(1)调用calloc后一定要判断一下申请内存是否成功,如果成功,返回值是分配空间的起始地址,如果失败,返回值是NULL。

(2)申请的总字节数是nmemb * size。

(3)malloc申请的内存,内存中存放的内容是随机不确定的;而calloc函数申请的内存中的内容是0。

(4)malloc多次申请的内存不一定连续,而calloc申请的多个内存块是连续的,它申请了nmemb * size个字节的连续内存空间。

使用方法类似于malloc,同样需要强制类型转换:p = (int*)calloc(1 ,n * sizeof(int));

7.3.4 realloc函数(重新申请内存)

(1)在malloc或calloc申请的内存后,紧挨着继续申请内存

(2)释放malloc或calloc申请的内存中的最后一部分

#include<stdlib.h>

void* realloc(void*s, unsigned int newsize);

在原先s指向的内存基础上重新申请内存,新内存大小为newsize字节,如果原先内存后面有足够大的空间则追加,如果后面内存不够用,就在堆区找一块newsize字节大小的内存申请,将原先内存上的内容拷贝过来,然后释放原来的内存,最后返回新内存的地址。

如果newsize比原先的内存小,则释放原先内存后面的存储空间,只保留前面的newsize字节。

返回值:新申请的内存的首地址

注意:malloc、calloc、realloc申请的内存从申请开始,直到free或者程序结束才释放。

7.4 内存泄漏

1、概念:申请的内存首地址丢了,找不到了,没办法使用了,也没办法释放了,这块内存就被泄露了。

例1:

int main()

{

char* p;

p = (char*)malloc(100);

p = "hello world";

return 0;

}

p不再指向申请的内存,而是指向了别的地方,也没有其他指针指向申请的内存,那么申请的那100个字节再也找不到了,动态申请的100个字节就被泄露了。

例2:

void fun()

{

char* p;

p = (char*)malloc(100);

}

int main()

{

fun();

fun();

return 0;

}

这时每次调用一个fun都会动态申请一个100字节的内存块,但没有释放,程序没有结束就会继续占用内存,这时就会内存泄漏。

解决方案1:谁申请谁释放

void fun()

{

char* p;

p = (char*)malloc(100);

free(p);

}

int main()

{

fun();

fun();

return 0;

}

解决方案2:申请后给别人,别人要释放

void fun()

{

char* p;

p = (char*)malloc(100);

free(p);

}

int main()

{

char* q;

q = fun();

free(q);

return 0;

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值