前言
本期分为三篇介绍动态内存管理相关内容,关注博主了解更多
博主博客链接:https://blog.csdn.net/m0_74014525
本期介绍动态内存函数,函数如何使用、函数格式、在使用在所需要的注意点及C/C++程序的内存开辟区域
系列文章
第一篇:C语言 — 动态内存管理(动态内存函数)
第二篇:C语言 — 常见的动态内存错误
第三篇:C语言 — 柔性数组
文章目录
- 前言
- 系列文章
- 一、动态内存分配是什么
- 二、为什么存在动态内存分配
- 三、动态内存函数的介绍
- 1. malloc
- 2. free
- 3. calloc
- 4. realloc
- 四、C/C++程序的内存开辟
- 1. 内存分配区域
- 总结
一、动态内存分配是什么
动态内存分配是指在程序运行期间由程序自己向操作系统请求分配一定大小的内存空间,以存储程序运行时所需的数据。 由于动态分配的内存空间在程序运行期间是可变的,所以它比静态分配更加灵活。
动态内存分配带来的好处是可以根据实际需要动态调整内存大小,从而避免浪费内存。 但是,如果程序员不小心管理动态分配的内存,就可能会导致内存泄漏或者内存溢出等问题,严重影响程序的性能和稳定性。因此,使用动态内存分配时需要注意内存的释放和管理。
常见的动态内存分配函数有 malloc
、calloc
、realloc
等。其中 malloc 分配指定大小的内存块,calloc 分配并初始化一定数量的内存块,realloc 可以重新调整已分配的内存块的大小。
二、为什么存在动态内存分配
我们已经掌握的内存开辟方式有:
int val = 20;//在栈空间上开辟四个字节
char arr[10] = {0};//在栈空间上开辟10个字节的连续空间
但是上述的开辟空间的方式有两个特点:
- 空间开辟大小是固定的。
- 数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配。
但是对于空间的需求,不仅仅是上述的情况。
有时候我们需要的空间大小在程序运行的时候才能知道,
那数组的编译时开辟空间的方式就不能满足了。
这时候就只能试试动态存开辟了。
三、动态内存函数的介绍
1. malloc
malloc
函数在C语言中用于在程序运行时向内存申请一块指定大小的内存空间。
函数格式:
void* malloc (size_t size);
其中,size_t是一个无符号整数类型,用于表示申请内存的字节数。malloc函数返回一个void指针,指向分配的内存空间的起始地址。如果分配失败,malloc函数返回空指针NULL。
函数特点:
- 如果开辟成功,则返回一个指向开辟好空间的指针。
- 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
- 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。
- 如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。
使用malloc函数申请内存时,需要注意以下几点:
1. | 申请的内存大小应该是变量或数据类型的字节数乘以需要存储或操作的元素个数,以保证申请到足够的内存空间。 |
2. | 申请到的内存空间必须使用free函数进行释放,否则会导致内存泄露。 |
3. | 申请到的内存空间不会被自动初始化,即其中的数据是随机的,需要手动进行初始化。 |
举例演示:
#include <stdio.h>
#include <stdlib.h>
int main() {
int *p;
p = (int*)malloc(10*sizeof(int)); //申请10个int类型数据的内存空间
if (p == NULL) { //判断申请是否成功
printf("Memory allocation failed.");
exit(1);
}
for (int i = 0; i < 10; i++) { //手动初始化数据
*(p+i) = i;
}
for (int i = 0; i < 10; i++) { //输出数据
printf("%d\t", *(p+i));
}
free(p); //释放内存空间
p=NULL; //将指针置为空
return 0;
}
2. free
free
函数是 C 语言中用来释放动态分配的内存的函数
函数格式:
void free (void* ptr);
其中,ptr 是之前调用 malloc、calloc 或 realloc函数返回的指针。调用 free 函数后,指针所指向的内存将会被操作系统回收,可以再次被分配给其他程序使用。
函数特点:
- 如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
- 如果参数 ptr 是NULL指针,则函数什么事都不做。
使用 free 函数的时候需要注意以下几点:
1. | 只能释放动态分配的内存,不能释放栈或全局变量中的内存。 |
2. | 如果多次释放同一个指针,会导致程序异常。 |
3. | 如果指针为空指针(NULL),则不会进行任何操作。 |
3. calloc
calloc
函数是C语言中的一个内存分配函数,用于在内存中分配指定大小的连续空间,并将其中的每个字节都初始化为0。
函数格式:
void* calloc (size_t num, size_t size);
其中,num表示要分配的元素数量,size表示每个元素的大小。函数返回一个指向新分配内存的指针,如果分配失败则返回NULL。
函数特点:
- 与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。
- 与malloc函数不同,calloc函数在分配内存时会自动清空分配的内存空间,所以一般用于需要初始化内存的情况。但它的缺点是比malloc函数慢,因为它需要在分配内存时进行清空操作。
使用calloc函数申请内存时,需要注意以下几点:
1. | 申请的内存大小应该是变量或数据类型的字节数乘以需要存储或操作的元素个数,以保证申请到足够的内存空间。 |
2. | 申请到的内存空间必须使用free函数进行释放,否则会导致内存泄露。 |
3. | 申请到的内存空间不会被自动初始化,即其中的数据是随机的,需要手动进行初始化。 |
4. | 区别于malloc,calloc 会在返回地址之前把申请的空间的每个字节初始化为全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函数来完成任务
4. realloc
realloc
函数是C语言中的一个库函数,用于重新分配动态分配的内存空间。
1.用于调整现有的内存块大小、
2.分配新的内存块
3.用于释放现有的内存块,当传递给它一个空指针时。
函数格式:
void* realloc(void* ptr, size_t size);
ptr表示指向已经动态分配的内存块的指针。
size表示需要重新分配的内存块的新尺寸。
返回值:如果分配失败,则返回NULL指针;否则返回一个新的指针,指向重新分配后的内存块。
函数特点:
使用realloc函数申请内存时,需要注意以下几点:
1. | 如果新的尺寸大于旧的尺寸,realloc函数将在原来的内存块后面分配额外的内存,使其达到新的尺寸。 |
2. | 如果新的尺寸小于旧的尺寸,realloc函数将会释放一部分内存,使其达到新的尺寸。 |
3. | 如果ptr是空指针,则等同于调用malloc函数。如果size是0,等同于调用free函数。 |
realloc在调整内存空间的是存在两种情况:
- 情况1:原有空间之后有足够大的空间
- 情况2:原有空间之后没有足够大的空间
情况1:
当是情况1 的时候,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化。
情况2:
当是情况2 的时候,原有空间之后没有足够多的空间时,
扩展的方法是:在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的是一个新的内存地址。
由于上述的两种情况,realloc函数的使用就要注意一些。
四、C/C++程序的内存开辟
1. 内存分配区域
C/C++程序内存分配的几个区域:
栈区(stack) | 在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。 栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返回地址等。 |
堆区(heap) | 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。分配方式类似于链表。 |
数据段 (静态区)(static) | 存放全局变量、静态数据。程序结束后由系统释放。 |
代码段 | 存放函数体(类成员函数和全局函数)的二进制代码。 |
总结
本期博客的重要点概况:
malloc
函数:用于动态内存的开辟
calloc
函数:也是用于动态内存开辟,区别于malloc,calloc函数会将每一个字节初始化为0
realloc
函数:用于扩展内存空间,需要注意增加内存的返回,分为情况1和2
free
函数:用于释放动态内存空间
如这篇博客对大家有帮助的话,希望 三连 支持一下 !!! 如果有错误感谢大佬的斧正 如有 其他见解发到评论区,一起学习 一起进步。