动态内存管理(C语言 VS C++)

目录

一.动态内存管理的前置知识

1.栈区

a.栈区的特点

b.注意事项

2.堆区

a.堆区的特点

b.注意事项

3.全局/静态区

a.作用域和生命周期

b.注意事项

4.常量区

 二.C语言动态内存管理

1.malloc 函数

a.接口简介与使用实例

b.注意要点

2.calloc 函数:

3.realloc 函数

a.接口简介与使用实例

b.注意要点

4.free 函数

三.C++动态内存管理

1.new 和 delete

a.理解使用实例

b.注意事项

2.运算符重载

a.operator new 与 operator delete函数

b. 定位new 表达式


一.动态内存管理的前置知识

我们在代码中用来存储数据的空间一共有这么几类:栈区、堆区、全局/静态区和常量区。那么,它们分别有什么用?相互间又有何区别?

1.栈区

栈区由编译器自动分配和释放,主要存储局部变量、函数参数等。栈区的内存分配是自动的,且按照后进先出(后定义的变量会先被释放)的原则进行。

a.栈区的特点

①后进先出:栈区的数据结构是一个栈,即只能在一端(栈顶)进行数据的压入(push)和弹出(pop)操作。新加入的数据会被放在栈顶,而最后加入的数据会最先被弹出。

②自动管理内存:栈区的内存分配和释放是由操作系统自动完成的,无需我们手动干预。当函数调用时,系统会为其分配一块栈空间用于存储局部变量和参数等;当函数返回时,系统会自动回收这块栈空间。

③存储效率高:由于栈区的数据结构相对简单,且内存分配和释放是自动完成的,因此栈区的存储效率较高,访问速度也较快。

b.注意事项

①避免栈溢出:栈溢出是指由于栈空间不足而导致的程序崩溃或异常,这一般是由于递归调用过深、局部变量过大或数组越界等问题,所以,在编写代码时,我们应该注意这类问题~~

②注意变量的作用域和生命周期:栈区中的变量具有明确的作用域和生命周期,它们只在定义它们的函数内部可见,并在函数返回时失效。

③避免野指针和内存泄漏:虽然栈区的内存是由系统自动管理的,但我们仍需注意避免野指针和内存泄漏等问题。例如,不要将栈区中的变量地址赋给全局指针或传递给其他函数,以免在变量失效后仍然使用该地址。

2.堆区

堆区是程序运行时用于动态分配内存的区域。与栈区不同,堆区的内存分配不是由编译器自动完成的,而是由程序员根据需要在程序运行时显式地申请和释放。这种动态内存分配方式提供了更大的灵活性,允许程序在运行时根据需要调整内存使用。

a.堆区的特点

堆区的内存通常是不连续的,因为系统使用链表等数据结构来管理空闲内存块。这种不连续性使得堆区的内存分配和释放相对复杂,但也提供了更大的灵活性。

b.注意事项

避免内存泄漏:内存泄漏是指程序在运行时未能正确释放已分配的内存,导致内存占用不断增加。为了避免内存泄漏,我们应确保在不再需要使用堆区上的内存时及时释放它

避免野指针:野指针是指访问指向无效内存地址的指针。这通常发生在释放内存后未将指针置NULL,然后再次使用该指针。所以,我们应在释放内存后将指针置为NULL。

3.全局/静态区

全局/静态区是内存中用于存储全局变量和静态变量的区域。全局变量是在所有函数外部定义的变量,而静态变量则可以通过在变量前加上 static 关键字来声明,无论是在函数内部还是外部。

a.作用域和生命周期

作用域:全局变量的作用域是整个程序,即它们可以在程序的任何位置被访问和修改。而静态变量仅在定义它们的函数内部可见。

生命周期:全局变量的生命周期从程序开始执行到程序结束。它们在程序启动时被分配内存,并在程序结束时被释放。

b.注意事项

命名冲突:由于全局变量的作用域是整个程序,因此在使用全局变量时需要特别小心,以避免命名冲突。静态全局变量可以帮助缓解这个问题,因为它们的作用域被限制在定义它们的文件内部。

内存管理:虽然全局/静态区的内存管理相对简单(由编译器自动处理),但也需要注意避免内存泄漏和野指针等问题。特别是当使用指向全局/静态区内存的指针时,要确保在不再需要时正确释放内存(如果适用)。然而,对于全局/静态区本身来说,由于它们的生命周期与程序相同,因此通常不需要手动释放内存。

多线程环境:在多线程环境中,对全局/静态区的访问需要特别小心,以避免竞态条件和数据不一致等问题。通常需要使用同步机制(如互斥锁)来保护对全局/静态区变量的访问。

4.常量区

常量存储区用于存储常量值,这些值在程序编译时就已经确定,并且在程序的整个执行期间都不会改变。常量存储区通常位于代码段中,与程序代码一起存储。

常量区存储的是程序中定义的常量值,如整数常量、字符常量、字符串常量等。对于字符串常量,常量区通常只存储一个副本,即使它们在程序中多次出现。这有助于节省内存空间。

常量区中的常量值在程序的整个执行期间都存在,直到程序终止

常量区中的内存通常是只读的,这意味着程序不能修改这些常量值。尝试修改常量存储区中的值可能会导致程序崩溃或未定义行为。

所以,所谓“动态内存管理”其实就是对堆上的空间做管理,不同语言对堆的操作接口不同,本文主要讲述C语言和C++对堆的操作接口~~

 二.C语言动态内存管理

在C语言中,动态内存管理是一种在程序运行时根据需要分配和释放内存(堆上的内存)的机制。与静态内存分配(其大小是固定的,在编译时确定)不同,动态内存管理允许程序在运行时灵活地调整其内存需求。C语言提供了几个函数来实现动态内存管理,主要包括 malloc、calloc、realloc和 free。

1.malloc 函数

a.接口简介与使用实例

void*  malloc ( size_t  size );

功能:malloc 函数用于分配指定大小的内存块,并返回一个指向该内存块的指针。

参数:size 是要开辟的空间大小,其单位是字节。

返回值:如果分配成功,返回指向分配的内存块的指针;如果分配失败,返回 NULL。

b.注意要点

①类型转换:malloc 返回的是一个 void* 类型的指针,因此在使用之前通常需要进行类型转换。

②内存初始化:malloc 分配的内存块是未初始化的,其内容是随机的。如果需要初始化内存,可以使用 calloc 函数,它会自动将分配的内存初始化为零

③内存泄漏:使用 malloc 分配的内存必须在使用完毕后通过 free 函数释放,否则会导致内存泄漏。

④检查返回值:始终检查 malloc 的返回值是否为 NULL,以确保内存分配成功。

2.calloc 函数

void* calloc (size_t num,  size_t size);

功能:calloc  函数用于分配内存,并将分配的内存初始化为零。它通常用于分配数组。

参数:num 是要分配的元素个数,size 是每个元素的大小(以字节为单位)。

返回值:如果分配成功,返回指向分配的内存块的指针;如果分配失败,返回 NULL 。

realloc 的注意要点与 malloc 类似,除了元素初始化~~

3.realloc 函数

a.接口简介与使用实例

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

功能:将 ptr 原先指向的堆空间大小调修改 size。

参数:ptr 是指向之前分配的内存块的指针,size 是新的大小(以字节为单位)。

返回值:如果调整成功,返回指向新分配(或调整大小)的内存块的指针;如果调整失败,返回 NULL(并且原来的内存块保持不变)。

b.注意要点

内存泄漏:如果 realloc 失败并返回 NULL,而原来的指针 str 不再被保存(例如,如果直接 str = realloc (str, 20*sizeof(char));  而没有检查返回值),则会导致内存泄漏,因为原来的内存块无法再被访问以进行 free 操作。

数据丢失:如果 realloc 成功但新大小小于旧大小,则超出新大小范围的数据会丢失。

性能:realloc 可能会移动内存块到新的位置,因此在处理大型数据结构或频繁的内存重新分配时,需要注意性能影响。

4.free 函数

void free(void*  ptr);

功能:free 函数用于释放之前通过 malloc、calloc 和 realloc 分配的内存。

参数:ptr 是指向要释放的内存块的指针。

注意:在释放内存后,应将指针设置为 NULL,以避免使用已释放的内存(即野指针问题)。将指针设置为 NULL 只是一个良好的编程习惯,并不是强制性的,因为一旦内存被释放,指针的值就不再有意义。

三.C++动态内存管理

与C语言类似,C++也提供了malloc、calloc、realloc和free等函数来进行动态内存管理。然而,C++引入了更高级、更面向对象的内存管理机制,即 new 和 delete 操作符,以及智能指针,如unique_ptr 和 shared_ptr。

1.new 和 delete

a.理解使用实例

1.动态申请内置类型数据空间时,new/calloc除了操作上有点不同,实质并没有太大区别;

*2.动态申请自定义类型数据空间时,new实例化出来的对象会调用类的构造函数,而malloc不会;delete释放空间时会调用类的析构函数,而free不会!!

如:A* p=new A[10];  会调用10次A的构造函数,delete[] p;会调用10次A的析构函数

malloc申请空间失败,会返回NULL,同时记录错误码;new申请空间失败,会直接抛异常!

用例助理解:

int* p1= new int;  开辟出大小是4个字节的堆空间,*p1默认为1。  delete p1;释放它

int* p2=new int(10); 开辟出大小是4个字节的堆空间,并给*P2赋值10。delete p2;资源释放

int* p3=new int[10];  开辟大小是40字节堆空间,每个元素初始值都是0。delete[] p2;资源释放。

int* p4=new int[10]{1,2,3}; //动态开辟一个大小是40字节的堆空间,其被初始化成{1,2,3,0,0,0...}

b.注意事项

①匹配使用:确保使用 new 分配的内存通过delete释放,使用new[]分配的内存通过delete[]释放。

②避免重复释放:不能对同一块内存使用多次delete或delete[]

③异常处理:如果new运算符在分配内存时失败(例如,由于堆内存不足),它会抛出一个异常。因此,在使用 new 时,可能需要考虑异常处理。

④操作符:new 和 delete是操作符,不是函数,而 malloc 和 calloc 是函数!!

2.运算符重载

a.operator new 与 operator delete函数

new 和 delete 是用户进行动态内存申请和释放的操作符,operator new和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过调用operator new全局函数来释放空间。

在C++中,new 和 delete 运算符本身是不能被直接重载的,就像其他基本的运算符(如+-*等)一样。然而,我们可以通过定义特殊的函数来间接地“重载”这些运算符的行为。

如类内重载:

b. 定位new 表达式

定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/56352.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flink Web UI 是使用和调试保姆级教程(持续更新)

Flink Web UI 是调试和监控 Flink 应用程序的重要工具,通过它,你可以实时查看正在运行的 Flink 任务的详细信息,包括作业的状态、性能指标、各子任务的运行情况、故障恢复情况等。Flink Web UI 的这些功能为开发者和运维人员提供了调试和优化…

软考系统分析师知识点十三:软件需求工程

前言 今年报考了11月份的软考高级:系统分析师。 考试时间为:11月9日。 倒计时:24天。 目标:优先应试,其次学习,再次实践。 复习计划第一阶段:扫平基础知识点,仅抽取有用信息&am…

FPGA采集adc,IP核用法,AD驱动(上半部分)

未完结,明天补全 IP核:集成的一个现有的模块 串口写好后基本不会再修改串口模块内部的一些逻辑,将串口.v文件添加进来,之后通过他的上层的接口去对他进行使用,所以我们打包IP,之后就不用去添加源文件了&a…

仿 Mac 个人网站开发 |项目复盘

一、前言 1.1 灵感来源 早年有幸看到国外大佬做的一个 基于 Web 的 Windows XP 桌面娱乐系统, 那时刚好有搭建一个个人博客的想法, 所以就想是否可以基于 WEB 实现一个仿 Mac UI 的个人博客, 以应用的形式来展示博客各个功能! 1.2 相关链接(求个 Star) 前端开源代码后端开源…

Linux之实战命令32:chroot应用实例(六十六)

简介: CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布:《Android系统多媒体进阶实战》🚀 优质专栏: Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏: 多媒体系统工程师系列【…

ali 231普通滑块82y版本

有需求可以联系博主 let v Died_in2021

【含开题报告+文档+PPT+源码】基于人脸识别的课堂考勤系统的设计与实现

开题报告 随着科技的不断发展,人脸识别技术已经逐渐渗透到各个领域,包括教育领域。传统的课堂考勤方式通常依赖于学生签到或教师手动记录,这种方式存在着许多不足之处,例如容易出现人为错误、耗费时间和资源等。为了解决这些问题…

诺贝尔经济学奖历史名单数据集(1969-2024年)

2024年诺贝尔经济学奖授予了达龙阿西莫格鲁(Daron Acemoglu)、西蒙约翰逊(Simon Johnson)和詹姆斯A罗宾逊(James A. Robinson),以表彰他们在理解制度如何影响经济发展方面的贡献。(“…

jmeter用csv data set config做参数化

在jmeter中,csv data set config的作用非常强大,用它来做批量测试和参数化非常好用。 csv data set config的常用配置项如下: Variable Names处,写上源文件中的参数名,用于后续接口发送请求时引用 Ignore first line…

泰克MDO3054示波器特性和规格Tektronix MSO3054 500M 四通道

Tektronix MDO3054 示波器,混合域,500 MHz,4 通道,5 GS/s 泰克 MDO3054 混合域示波器是终极 6 合 1 集成示波器,包括可选的集成频谱分析仪、任意函数发生器、逻辑分析仪、协议分析仪和数字电压表/计数器。泰克 MDO305…

python项目实战——下载美女图片

python项目实战——下载美女图片 文章目录 python项目实战——下载美女图片完整代码思路整理实现过程使用xpath语法找图片的链接检查链接是否正确下载图片创建文件夹获取一组图片的链接获取页数 获取目录页的链接 完善代码注意事项 完整代码 import requests import re import…

Java算术运算符 C语言的二维数组初始化

1. //算术运算符 public static void main(String[] args) {System.out.println(3.25.01);//若有小数参与,有可能不精确System.out.println(5-1);System.out.println(5*2);System.out.println(10.0/3);//这里不精确System.out.println(10%2);System.out.println();…

2024.10月16日- Vue.js(1)

一 VUE概述与环境搭建 1.1 Vue概述 1.1.1 简介 Vue (发音为 /vjuː/,类似 view) 是一款轻量级的用于构建用户界面的 渐进式的JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高…

Vivado - Aurora 8B/10B IP

目录 1. 简介 2. 设计调试 2.1 Physical Layer 2.2 Link Layer 2.3 Receiver 2.4 IP 接口 2.5 调试过程 2.5.1 Block Design 2.5.2 释放 gt_reset 2.5.3 观察数据 3. 实用技巧 3.1 GT 坐标与布局 3.1.1 选择器件并进行RTL分析 3.1.2 进入平面设计 3.1.3 收发器布…

堆排序(C++实现)

参考: 面试官:请写一个堆排序_哔哩哔哩_bilibiliC实现排序算法_c从小到大排序-CSDN博客 堆的基本概念 堆排实际上是利用堆的性质来进行排序。堆可以看做一颗完全二叉树。 堆分为两类: 最大堆(大顶堆):除根…

Java-IO流使用场景

Java IO 流是Java编程中非常重要的组成部分,用于处理文件读写、网络通信等数据传输任务。 1. 字节流 1.1 读取文件 import java.io.FileInputStream; import java.io.IOException;public class ReadFileExample {public static void main(String[] args) {try (FileInputSt…

Unity实现自定义图集(一)

以下内容是根据Unity 2020.1.0f1版本进行编写的   Unity自带有图集工具,包括旧版的图集(设置PackingTag),以及新版的图集(生成SpriteAtlas)。一般来说,unity自带的图集系统已经够用了,但是实际使用上还是存在一些可优化的地方,例如加载到Canvas上的资源,打图集不能…

PyQt 入门教程(3)基础知识 | 3.2、加载资源文件

文章目录 一、加载资源文件1、PyQt5加载资源文件2、PyQt6加载资源文件 一、加载资源文件 常见的资源文件有图像与图标,下面分别介绍下加载资源文件的常用方法 1、PyQt5加载资源文件 2、PyQt6加载资源文件 PyQt6版本暂时没有提供pyrcc工具,下面介绍下在不…

雷池社区版本SYSlog使用教程

雷池会对恶意攻击进行拦截,但是日志都在雷池机器上显示 如何把日志都同步到相关设备进行统一的管理和分析呢? 如需将雷池攻击日志实时同步到第三方服务器, 可使用雷池的 Syslog 外发 功能 启用 Syslog 外发 进入雷池 系统设置 页面, 配置 Syslog 设置…

北京京恋在喧嚣的都市中助你邂逅自己的爱情

北京的夜晚,灯火璀璨,车水马龙。刘凡站在他位于国贸的公寓阳台上,望着眼前熙熙攘攘的街道,心中却有一丝落寞。32岁的他,是一家知名互联网公司的中层管理,事业有成,收入稳定,甚至朋友…