来不及悼念它了~接下来登场的是动态内存分配的malloc与realloc以及free函数

本文主要是介绍来不及悼念它了~接下来登场的是动态内存分配的malloc与realloc以及free函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

相信各位经常看见一个词语“动态内存分配 ”,那么也经常看见malloc这个函数,但你有时又看见realloc函数,你也听说过内存释放,其实动态内存分配就是运用这些函数来进行的那么今天你可以通过这篇文章来了解和区分这些函数!希望大家多多支持!也希望官方大大多给曝光!

目录

malloc

realloc

free


malloc
 

我们先看官方解释(后边有代码解释比较通俗易懂):


 malloc  是 C 语言标准库中的一个函数,用于动态分配内存。它的主要作用是在运行时为程序分配所需的内存空间。
 
函数原型:
 
 

void *malloc(size_t size);


 
 
参数说明:
 
-  size :要分配的内存块的大小,以字节为单位。
 
函数的执行情况:
 
1. 分配内存: malloc  函数会在堆(heap)上寻找足够的连续内存空间来满足指定的大小需求。
2. 返回指针:如果成功分配到了所需的内存空间, malloc  将返回一个指向新分配内存块起始位置的指针。
3. 处理错误:如果没有足够的可用内存来满足分配请求, malloc  将返回  NULL 。这表示内存分配失败。

 
下面我们看看官方的详细要点和注意事项:
 
1. 内存分配:通过调用  malloc ,你可以在程序运行时根据需要分配任意大小的内存块。
2. 返回的指针:返回的指针是一个void*类型的指针,这意味着它没有特定的数据类型。在使用分配的内存时,你需要进行类型转换,以确保正确的访问。
3. 内存管理责任:使用  malloc  分配的内存需要由你负责管理。这包括在不再需要时使用  free  函数释放内存,以避免内存泄漏。
4. 内存对齐: malloc  可能会根据系统的要求和硬件的特性进行内存对齐,以提高性能或满足特定的硬件要求。
5. 内存安全性:在使用分配的内存时,要确保遵循正确的内存访问规则,避免越界访问或其他内存错误。
6. 错误检查:由于内存分配可能失败,所以在使用返回的指针之前,务必检查是否为  NULL 。如果是  NULL ,你需要采取适当的错误处理措施。
7. 内存大小计算:确保正确计算所需的内存大小,包括考虑数据类型的大小和任何额外的内存需求。
8. 多层分配和释放:在复杂的程序结构中,可能会有多个层次的内存分配和释放。确保按照正确的顺序进行释放,以避免内存泄漏或其他问题。
9. 避免内存碎片:频繁的分配和释放内存可能导致内存碎片的产生,降低内存的利用效率。尽量合理规划内存使用,减少不必要的分配和释放。
 


接下来我给大家演示一段简单的代码使用方法:
 

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>int main() {int * ptr = (int *)malloc(10 * sizeof(int));if (ptr == NULL) {printf("内存开辟分配失败\n");return 1;}//对分配内存进行填充即初始化for (int i = 0; i < 10; i++) {ptr[i] = i;}printf("已分配到内存空间其地址为: %p\n", ptr);//我们可以尝试使用空间打印出初始化内容for (int i = 0; i < 10; i++){printf("%d ", ptr[i]);}//释放内存free(ptr);return 0;
}



 
代码简单解析:在这个示例中,使用  malloc  分配了一个包含 10 个整数的内存块。然后,可以通过返回的指针访问和使用分配的内存。


 
接下来我们看一个与malloc功能相似的函数realloc函数。


realloc

我们先看官方解释(后边有代码解释比较通俗易懂):


 realloc  是 C 语言标准库中的一个函数,用于动态调整已经分配的内存块的大小。它的主要目的是在不丢失数据的情况下,根据新的需求重新分配内存。
 
函数原型:
 
 

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


 
 
参数说明:
 
-  ptr :指向要调整大小的内存块的指针。这是之前通过  malloc  或其他方式分配的内存的指针。
-  size :新的内存块大小,以字节为单位。

 
函数的执行情况:
 
1. 调整内存大小: realloc  尝试根据提供的新大小  size  调整内存块的大小。
2. 内存重新分配:如果有足够的可用内存来满足新的大小要求, realloc  会重新分配一块内存,并将原内存块的内容复制到新的内存块中。
3. 保持数据完整性:这样可以确保在调整大小过程中不会丢失已存在的数据。
4. 返回新的指针: realloc  返回一个新的指针,指向调整后的内存块。如果内存调整成功,你应该使用返回的新指针来访问调整后的内存。
5. 处理错误情况:如果没有足够的内存来满足新的大小要求,或者其他原因导致调整失败, realloc  将返回  NULL 。在这种情况下,原指针  ptr  仍然有效,但你需要处理这种错误情况,例如采取适当的措施来释放原内存块。



 
官方realloc  的详细要点和注意事项(能看懂就看看不懂也没关系
 

1. 原指针的有效性:在调用  realloc  后,原指针  ptr  可能会被更新为新的内存地址,也可能保持不变。这取决于实现和具体情况。因此,在使用调整后的内存时,应该始终使用  realloc  返回的新指针。
2. 内存复制:如果新的大小小于原内存块的大小, realloc  可能会缩小内存块,但会尝试保持数据的完整性。这可能涉及到将部分数据复制到新的较小内存块中。
3. 内存释放:如果使用  realloc  调整内存大小后不再需要原内存块,仍然需要使用  free  函数来释放内存。这可以通过调用  free  并传递  realloc  返回的新指针来完成。
4. 处理返回值:务必检查  realloc  的返回值,以确保内存调整成功。如果返回  NULL ,表示调整失败,可能需要采取适当的错误处理措施。
5. 内存连续性:尽管  realloc  尝试保持内存的连续性,但不能保证调整后的内存块在内存中仍然是连续的。在某些情况下,可能会导致内存碎片化。
6. 性能考虑:频繁地进行内存调整可能会影响程序的性能,因为可能需要进行内存复制和重新分配。在设计程序时,尽量避免过于频繁地调整内存大小。


下面是用代码给大家展示如何使用:
 

#include <stdio.h>#include <stdlib.h>int main() 
{int * ptr = (int *)malloc(10 * sizeof(int));if (ptr == NULL) {printf("内存开辟分配失败\n");return 1;}//对分配内存进行填充即初始化for (int i  = 0; i < 10; i++) {ptr[i] = i;}printf("原来空间指针地址:%p\n", ptr);ptr = (int *)realloc(ptr, 20 * sizeof(int));if(ptr == NULL){printf("内存空间改变失败\n");return 1;}printf("realloc后的指针地址:%p\n", ptr);//访问和使用调整后的内存for (int i = 0; i < 20; i++){printf("%d ", ptr[i]);}//释放内存free(ptr);return 0;
}


 
代码简单解释:首先使用  malloc  分配了一个包含 10 个整数的内存块。然后,通过  realloc  将内存块的大小调整为 20 个整数。根据返回的新指针,可以访问和使用调整后的内存。

需要注意的是:这里后面的负数是因为我们没有对扩大后的内存进行初始化,所以系统随机打印出一个值。
 
 


free

我们先看官方解释(后边有代码解释比较通俗易懂):

 free  是 C 语言标准库中的一个函数,用于释放之前通过  malloc  或其他内存分配函数分配的内存空间。它的主要目的是将不再使用的内存归还给操作系统,以避免内存泄漏。
 
函数原型:
 
 

void free(void *ptr);


 
 
参数说明:
 
-  ptr :指向要释放的内存块的指针。这个指针应该是之前通过  malloc 、 calloc  或  realloc  等函数分配的内存的指针。
 
函数执行情况:


1.  free  函数接受一个指针作为参数,并将该指针所指向的内存块标记为可供操作系统再次使用的状态。
2. 释放的内存可能会被操作系统用于其他分配请求或进行内存管理的操作。
3. 一旦内存被释放,使用该指针访问内存是不安全的,可能导致未定义的行为。
 

官方 free  函数的详细要点和注意事项(能看懂就看看不懂也没关系):
 
1. 释放责任:使用  malloc  或其他函数分配的内存必须使用  free  进行释放,以避免内存泄漏。
2. 指针有效性:在调用  free  之前,确保指针  ptr  是有效的,并且是之前分配的内存的指针。错误地释放无效指针可能导致程序崩溃或其他问题。
3. 单步释放:每次调用  free  只能释放一个之前分配的内存块。如果有多个内存块需要释放,需要分别调用  free 。
4. 释放顺序:在复杂的程序结构中,确保按照正确的顺序释放内存,特别是在存在多层分配和引用的情况下。
5. 避免重复释放:对同一个内存块多次调用  free  是不正确的,这样的操作可能导致程序错误。
6. 释放后指针:一旦使用  free  释放了内存,就不应该再使用指针  ptr 。将其设置为  NULL  是一个好的习惯,以避免误操作。
7. 错误处理:在调用  free  之后,不应该再检查  free  的返回值,因为它通常不会返回任何有用的信息。如果内存分配或释放过程中出现问题,通常会在其他地方(如  malloc )返回错误。
8. 内存管理原则:良好的内存管理原则包括在适当的时候分配内存、正确地使用内存、及时释放不再需要的内存,并处理可能出现的错误情况。
 

下面展示更易懂的代码:
 

 

#include <stdio.h>
#include <stdlib.h>int main() {int * ptr = (int *)malloc(10 * sizeof(int));if (ptr == NULL) {printf("内存开辟分配失败\n");return 1;}//释放内存free(ptr);return 0;
}


 
 
在这个示例中,通过  malloc  分配内存,使用完后使用  free  进行释放。
 
正确使用  malloc  和  free  对于确保程序的内存安全性和可靠性非常重要。同时,还要注意其他与内存管理相关的问题,如内存泄漏、缓冲区溢出等。


接下来我们来一个大总结一下:

1. 功能不同:

 malloc  用于分配一块新的内存空间。
realloc  用于调整已经分配的内存空间的大小。


2. 内存处理:
 malloc  分配的是全新的内存块,如果之前已经分配了内存,使用  malloc  会创建一个新的内存块,并复制原有数据到新的内存块。
  realloc  可以在不改变已有数据的情况下调整内存块的大小。如果新的大小小于原来的大小, realloc  可能会缩小内存块并保持数据的完整性。如果新的大小大于原来的大小, realloc  可能会重新分配一块更大的内存,并复制已有数据到新的内存块。


3. 返回值:
  malloc  返回一个指向新分配内存块的指针,如果分配失败,则返回  NULL 。
  realloc  返回一个指向调整后内存块的指针,如果调整失败(例如没有足够的内存可用),则返回  NULL 。


4. 原指针的有效性:
使用  malloc  后,原指针通常不再有效,需要将其更新为新分配内存的指针。
 使用  realloc  后,原指针可能仍然有效,也可能被更新为新的地址。这取决于  realloc  的实现和具体情况。


5. 内存释放:
 使用  malloc  分配的内存需要通过  free  函数来释放。
-使用  realloc  调整内存大小后,如果不再需要原来的内存块,仍然需要使用  free  来释放。
 


最后最后文章结束,望官方大大给个热门。

这篇关于来不及悼念它了~接下来登场的是动态内存分配的malloc与realloc以及free函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/707339

相关文章

【操作系统】信号Signal超详解|捕捉函数

🔥博客主页: 我要成为C++领域大神🎥系列专栏:【C++核心编程】 【计算机网络】 【Linux编程】 【操作系统】 ❤️感谢大家点赞👍收藏⭐评论✍️ 本博客致力于知识分享,与更多的人进行学习交流 ​ 如何触发信号 信号是Linux下的经典技术,一般操作系统利用信号杀死违规进程,典型进程干预手段,信号除了杀死进程外也可以挂起进程 kill -l 查看系统支持的信号

java中查看函数运行时间和cpu运行时间

android开发调查性能问题中有一个现象,函数的运行时间远低于cpu执行时间,因为函数运行期间线程可能包含等待操作。native层可以查看实际的cpu执行时间和函数执行时间。在java中如何实现? 借助AI得到了答案 import java.lang.management.ManagementFactory;import java.lang.management.Threa

SQL Server中,isnull()函数以及null的用法

SQL Serve中的isnull()函数:          isnull(value1,value2)         1、value1与value2的数据类型必须一致。         2、如果value1的值不为null,结果返回value1。         3、如果value1为null,结果返回vaule2的值。vaule2是你设定的值。        如

tf.split()函数解析

API原型(TensorFlow 1.8.0): tf.split(     value,     num_or_size_splits,     axis=0,     num=None,     name='split' ) 这个函数是用来切割张量的。输入切割的张量和参数,返回切割的结果。  value传入的就是需要切割的张量。  这个函数有两种切割的方式: 以三个维度的张量为例,比如说一

神经网络第三篇:输出层及softmax函数

在上一篇专题中,我们以三层神经网络的实现为例,介绍了如何利用Python和Numpy编程实现神经网络的计算。其中,中间(隐藏)层和输出层的激活函数分别选择了 sigmoid函数和恒等函数。此刻,我们心中不难发问:为什么要花一个专题来介绍输出层及其激活函数?它和中间层又有什么区别?softmax函数何来何去?下面我们带着这些疑问进入本专题的知识点: 1 输出层概述 2 回归问题及恒等函数 3

神经网络第一篇:激活函数是连接感知机和神经网络的桥梁

前面发布的文章介绍了感知机,了解了感知机可以通过叠加层表示复杂的函数。遗憾的是,设定合适的、能符合预期的输入与输出的权重,是由人工进行的。从本章开始,将进入神经网络的学习,首先介绍激活函数,因为它是连接感知机和神经网络的桥梁。如果读者认知阅读了本专题知识,相信你必有收获。 感知机数学表达式的简化 前面我们介绍了用感知机接收两个输入信号的数学表示如下:

vscode python pip : 无法将“pip”项识别为 cmdlet、函数、脚本文件或可运行程序的名称

在vscode中控制台运行python文件出现:无法将"pip”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。 使用vscode开发python,需要安装python开发扩展: 本文已经安装,我们需要找的是python安装所在目录,本文实际路径如下: 如果在本文路径中没有此目录,请尝试在C盘中搜索 python,搜索到相关python目录后,点击Python 3.9进入目录,

C语言入门系列:初识函数

文章目录 一,C语言函数与数学函数的区别1,回忆杀-初中数学2,C语言中的函数 二, 函数的声明1,函数头1.1,函数名称1.2,返回值类型1.3,参数列表 2,函数体2.1,函数体2.2,return语句 三,main函数四,函数的参数与传递方式1,实参和形参1.1,函数定义(含形参)1.2,函数调用(使用实参) 2,参数传递方式2.1,值传递2.2,引用传递 五,函数原型与预声明1,

Linux C/C++ socket函数

目录 socket函数 函数原型 头文件 功能 返回值 参数 错误码 socket函数 函数原型 int socket(int domain, int type, int protocol); 头文件                 #include <sys/types.h>                 #include <sys/socket.h>

C语言 gets函数 puts函数 getchar函数

gets函数从标准输入读取一行文本并把它存储于作为参数传递给它的数组中。 一行输入由一串字符组成,以一个换行符(newline)结尾。 gets函数丢弃换行符,并在改行的末尾存储一个NULL字节(一个NULL字节是指字节模式为全0的字节,类似’\0’这样的字符常量)。然后,gets函数返回一个非NULL值,表示该行已被成功读取。 当gets函数被调用,但事实上不存在输入行时,它就返回NULL值,表