内存的静态分配和动态分配的区别

2023-05-16

 内存的静态分配和动态分配的区别主要是两个:

      一是时间不同。静态分配发生在程序编译和连接的时候。动态分配则发生在程序调入和执行的时候。

      二是空间不同。堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由函数malloc进行分配。不过栈的动态分配和堆不同,他的动态分配是由编译器进行释放,无需我们手工实现。    

对于一个进程的内存空间而言,可以在逻辑上分成3个部份:代码区,静态数据区和动态数据区。动态数据区一般就是“堆栈”。“栈(stack)”和“堆(heap)”是两种不同的动态数据区,栈是一种线性结构,堆是一种链式结构。进程的每个线程都有私有的“栈”,所以每个线程虽然代码一样,但本地变量的数据都是互不干扰。一个堆栈可以通过“基地址”和“栈顶”地址来描述。全局变量和静态变量分配在静态数据区本地变量分配在动态数据区,即堆栈中。程序通过堆栈的基地址和偏移量来访问本地变量。

 

一般,用static修饰的变量,全局变量位于静态数据区。函数调用过程中的参数,返回地址,EBP和局部变量都采用栈的方式存放。

 

 

所谓动态内存分配就是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法。动态内存分配不象数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小。
例如我们定义一个float型数组:float score[100];   
但是,在使用数组的时候,总有一个问题困扰着我们:数组应该有多大?在很多的情况下,你并不能确定要使用多大的数组,比如上例,你可能并不知道我们要定义的这个数组到底有多大,那么你就要把数组定义得足够大。这样,你的程序在运行时就申请了固定大小的你认为足够大的内存空间。即使你知道你想利用的空间大小,但是如果因为某种特殊原因空间利用的大小有增加或者减少,你又必须重新去修改程序,扩大数组的存储范围。这种分配固定大小的内存分配方法称之为静态内存分配。但是这种内存分配的方法存在比较严重的缺陷,特别是处理某些问题时:在大多数情况下会浪费大量的内存空间,在少数情况下,当你定义的数组不够大时,可能引起下标越界错误,甚至导致严重后果。
我们用动态内存分配就可以解决上面的问题. 所谓动态内存分配就是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法。动态内存分配不象数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小。从以上动、静态内存分配比较可以知道动态内存分配相对于景泰内存分配的特点:
   1、不需要预先分配存储空间;
   2、分配的空间可以根据程序的需要扩大或缩小。
要实现根据程序的需要动态分配存储空间,就必须用到malloc函数.
malloc函数的原型为:void *malloc (unsigned int size) 其作用是在内存的动态存储区中分配一个长度为size的连续空间。其参数是一个无符号整形数,返回值是一个指向所分配的连续存储域的起始地址的指针。还有一点必须注意的是,当函数未能成功分配存储空间(如内存不足)就会返回一个NULL指针。 所以在调用该函数时应该检测返回值是否为NULL并执行相应的操作。
静态内存是在程序一开始运行就会分配内存,直到程序结束了,内存才被释放。
动态内存是在程序调用在程序中定义的函数时才被分配,函数调用结束了,动态内存就释放。
static int a;这是定义了一个静态的变量
int a;这是定义了一个动态的变量;
静态内存可以用于求阶层。
例如:
jiechen(int i)
{static int a=1;
for(;a<=i,a++)
return a*i;
}
#include"stdio.h"
main()
{int a,i;
printf("enter number:")
scanf("%d",&a);
for(i=1;i<=a;i++)
printf("i!=%d\n",jiechen(i));

}
运行
输入3
结果为1!=1
          2!=2
          3!=3
 
 
由malloc系统函数分配的内存就是从堆上分配内存。从堆上分配的内存一定要自己释放。用free释放,不然就是术语——“内存泄露”(或是“内存漏洞”)—— Memory Leak。于是,系统的可分配内存会随malloc越来越少,直到系统崩溃。还是来看看“栈内存”和“堆内存”的差别吧。

    栈内存分配
    —————
    char*
    AllocStrFromStack()
    {
        char pstr[100];
        return pstr;
    }
  
    堆内存分配
    —————
    char*
    AllocStrFromHeap(int len)
    {
        char *pstr;
       
        if ( len <= 0 ) return NULL;
        return ( char* ) malloc( len );
    }

对于第一个函数,那块pstr的内存在函数返回时就被系统释放了。于是所返回的char*什么也没有。而对于第二个函数,是从堆上分配内存,所以哪怕是程序退出时,也不释放,所以第二个函数的返回的内存没有问题,可以被使用。但一定要调用free释放,不然就是Memory Leak!

在堆上分配内存很容易造成内存泄漏,这是C/C++的最大的“克星”,如果你的程序要稳定,那么就不要出现Memory Leak。所以,我还是要在这里千叮咛万嘱付,在使用malloc系统函数(包括calloc,realloc)时千万要小心。

记得有一个UNIX上的服务应用程序,大约有几百的C文件编译而成,运行测试良好,等使用时,每隔三个月系统就是down一次,搞得许多人焦头烂额,查不出问题所在。只好,每隔两个月人工手动重启系统一次。出现这种问题就是Memery Leak在做怪了,在C/C++中这种问题总是会发生,所以你一定要小心。一个Rational的检测工作——Purify,可以帮你测试你的程序有没有内存泄漏。

我保证,做过许多C/C++的工程的程序员,都会对malloc或是new有些感冒。当你什么时候在使用malloc和new时,有一种轻度的紧张和惶恐的感觉时,你就具备了这方面的修养了。
对于malloc和free的操作有以下规则:

1) 配对使用,有一个malloc,就应该有一个free。(C++中对应为new和delete)
2) 尽量在同一层上使用,不要像上面那种,malloc在函数中,而free在函数外。最好在同一调用层上使用这两个函数。
3) malloc分配的内存一定要初始化。free后的指针一定要设置为NULL。   

注:虽然现在的操作系统(如:UNIX和Win2k/NT)都有进程内存跟踪机制,也就是如果你有没有释放的内存,操作系统会帮你释放。但操作系统依然不会释放你程序中所有产生了Memory Leak的内存,所以,最好还是你自己来做这个工作。(有的时候不知不觉就出现Memory Leak了,而且在几百万行的代码中找无异于海底捞针,Rational有一个工具叫Purify,可能很好的帮你检查程序中的Memory Leak)
 
第一个例子也讲得不清楚。所谓系统释放,应该是指系统在自己的表里把这段内存标记为可以使用,以后可以被别的程序使用,所以第一个例子会造成程序能访问到已经释放的内存空间,是越界,会造成不可预测的情况。
系统一般不会自动去清除释放空间内的数据,而是由以后的程序来覆盖。所以很多程序开头都会做MEMSET(...),就是为了防止这种垃圾数据的情况。
如果在程序运行中要改变内存块的大小,可以用RALLOC()函数,它能在原来地址上重新分配一块空间,不过是用的时候要小心,也是比较容易出问题
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

内存的静态分配和动态分配的区别 的相关文章

  • Ubuntu系统安装、配置与美化(Ubuntu20.04)

    阅读指南 目的 本文的写作目的在于帮助完全零基础的小白不理解原理而可以无脑安装Linux系统 xff0c 同时也是为自己进行的一个整理 xff0c 相较于网上大多数的教程 xff0c 本教程将一些内容进行了整合与整理 xff0c 加之本人在
  • 【模电】0010 正弦波产生电路(RC正弦波振荡电路)

    上一节我们分析了使用比较器产生方波和正弦波的电路 xff0c 其本质上是在电容充放电的一段延时后 xff0c 利用比较器产生电平翻转 而本节分析的正弦波产生电路 xff0c 产生的原理不同 1 xff09 振荡产生的原理 正弦波产生电路 x
  • 一种锂电池充放电及外部供电自动切换的电路

    介绍一种单节锂电池充放电一体的电路 该电路在外接电源时 xff0c 使用外接电源供电 xff0c 并且为锂电池充电 xff1b 在无外接电源时 xff0c 系统自动切换为锂电池供电 电路的原理如下图 xff1a 1 xff09 图中VBUS
  • 【STM32+cubemx】0008 HAL库开发:ADC的四种用法:轮询、中断、DMA、定时器触发

    ADC即模数转换器 xff0c 能把模拟量 xff08 电压 xff09 转换为数字量 这一节我们讲讲stm32的ADC用法 xff0c stm32自带的ADC有四种用法 xff1a 轮询 中断 DMA 定时器触发 1 xff09 ADC轮
  • 【STM32+cubemx】0011 HAL库开发:I2C总线访问加速度传感器ADXL345

    本节我们介绍I2C总线 xff0c 并使用stm32的I2C总线来访问加速度传感器ADXL345 1 xff09 I2C基础知识 I2C总线通信比较适合设备内部各芯片间的通信 xff0c 它只需要两根信号线 I2C可以挂载多个主机和从机 x
  • 【STM32+cubemx】0013 HAL库开发:SPI总线访问气压计BMP280/BME280

    本节我们介绍stm32的SPI总线接口 xff0c 并使用SPI接口来访问气压计BMP280 1 xff09 SPI基础知识 SPI xff08 Serial Peripheral Interface xff09 串行外围设备接口 xff0
  • 【STM32+cubemx】0017 HAL库开发:usb HID鼠标设备实现

    Cubemx可以生成多种usb设备的初始化代码 xff0c 本节我们就使用它来生成一个usb HID鼠标的工程 xff0c 在开发板上运行以后 xff0c 可以模拟usb鼠标的功能 1 xff09 生成USB HID工程 仍然使用串口工程
  • 【STM32+cubemx】0018 HAL库开发:自定义usb HID设备实现

    前面几节我们使用Cubemx生成了usb的两个使用例子 xff08 虚拟串口 HID鼠标 xff09 xff0c 本节我们进一步学习 xff0c 如何用生成自定义的HID设备 本节的例子在开发板上运行以后 xff0c 可以通过usb HID
  • 【STM32+cubemx】0026 HAL库开发:NRF24L01无线2.4G通信模块的应用

    NRF24L01是NORDIC公司生产的一款无线通信通信芯片 xff0c 可以工作在免费开放的2 4GHz频段 xff1b 通信速率可以达到最高2Mbps xff1b MUC可以使用SPI接口与它交互 本节我们就来使用stm32驱动NRF2
  • 【STM32+cubemx】0027 HAL库开发:MPU6050陀螺仪和加速度计数据的获取和校准

    在制作平衡车或者飞行器时 xff0c 不可避免地需要知道设备本身的姿态 xff0c 一般我们使用陀螺仪和加速度计来获取这些信息 陀螺仪用来测量物体的角度 传统的机械式陀螺的原理 xff0c 和我们小时候玩的陀螺一样 xff0c 是利用了高速
  • 【STM32+cubemx】0028 HAL库开发:MPU6050官方DMP的移植和使用(续上节)

    上一节我们使I2C总线获取了MPU6050的三轴加速度 三轴角速度 xff0c 并且介绍了一种简单的初始状态校准方法 xff1b 这一节我们继续 xff0c 在已有的底层驱动基础上 xff0c 移植MPU6050芯片官方的DMP库 xff0
  • ​Jetson Nano 2G ROS 调用 CSI摄像头

    1 安装ROS的CSI摄像头软件包 TX2推荐安装jetson strong csi strong strong cam strong xff0c 而Nano推荐安装jetson nano strong csi strong strong
  • 【FreeRTOS】01 初识freertos操作系统,第一个任务

    1 xff09 概述 最近打算写一个实时操作系统编程的系列 操作系统分很多种 xff0c 有大型的复杂 功能齐全操作系统 xff0c 也有小型的代码几百行的操作系统内核 xff1b 也有实时和非实时之分 这里我们学习可以运行在资源很少的类单
  • 【FreeRTOS】02 任务的创建

    上一节我们利用cubemx自动生成了一个实例 xff0c 它建立了两个用户任务和一个默认任务 xff0c 并成功运行起来了 本节我们将分析一下FreeRTOS任务创建的过程 xff0c 并结合创建时需要的参数讲解一下FreeRTOS任务的一
  • 【FreeRTOS】08 互斥信号量、优先级反转问题

    本节继续讲freeRTOS的信号量 xff0c 先讲一个与抢占式调度和信号量有关的经典问题 优先级反转 xff0c 再讲互斥信号量 1 xff09 什么是优先级反转 假设这样一种情况 xff1a 在一个具有抢占式调度的操作系统中 xff0c
  • 陀螺仪与加速度计的姿态融合——互补滤波

    本篇文章我们来讲讲如何将陀螺仪和加速度计的数据结合起来 xff0c 获取更准确的姿态数据 xff0c 使用的是互补滤波的方法 阅读本文需有一定的知识基础 xff0c 可以参见作者以前MPU6050的两篇文章 xff1a MPU6050陀螺仪
  • 【电磁兼容】01 高速电路入门知识

    1 什么是高速电路 xff1f 一般情况下 xff0c 我们在讨论电路的特性时 xff0c 一个基本的常识 xff0c 是认为一条导线上各处的电压 xff08 或者说信号 xff09 在同一时刻是相等的 以上结论在低速电路时是没问题的 xf
  • 【电磁兼容】02 信号接地设计

    大家好 xff0c 我是学电子的小白白 今天我们来讲一讲电路设计中的接地问题 在电气系统中 xff0c 接地涉及到两个概念 xff0c 一个是安全接地 xff0c 一个是信号接地 xff1b 前者一般是在强电设备中 xff0c 外壳接地防止
  • 【电磁兼容】03 高速数字电路的阻抗匹配

    大家好 xff0c 我是学电子的小白白 这篇文章我们来聊一聊阻抗匹配 xff0c 尤其是高速数字电路的阻抗匹配的问题 1 xff09 什么是阻抗匹配 阻抗匹配是指信号源 传输线 负载之间的一种搭配方式 由于实际的信号源都是有内阻的 xff0
  • vscode开发技巧篇

    1 cherry pick 可以将某个分支上的一次提交或者多次提交在当前选中分支上重演 git 操作 xff1a 单个 xff1a git cherry pick commitId git log 查看 多个 xff1a git cherr

随机推荐

  • VIO标定(相机和IMU的标定)

    VIO标定 VIO标定分为三个部分 xff0c 相机的标定 xff0c IMU的标定 xff0c 相机和IMU的联合标定 双目相机相机内参标定 xff08 单目相机可以用类似的方法 xff09 标定单目和标定双目的区别 标定单目相机就是简单
  • OpenCV——目标追踪

    文章素材来源 Fu Xianjun All Rights Reserved 目标追踪算法介绍 目标跟踪是计算机视觉领域的一个重要问题 xff0c 目前广泛应用在体育赛事转播 安防监控和无人机 无人车 机器人等领域 目标跟踪的研究领域 单目标
  • ArduPilotMega (APM) 是市面上最强大的基于惯性导航的开源自驾仪

    http bbs loveuav com thread 54 1 1 html ArduPilotMega APM 是市面上最强大的基于惯性导航的开源自驾仪 特性包括 免费开源固件 xff0c 支持飞机 xff08 34 ArduPlane
  • 以虎贲T710为核心的高性能AI开发板-BU99开发板

    文章目录 虎贲T710BU99开发板BU99开发板简介BU99开发板主要优势BU99开发板参数介绍BU99开发板配件 虎贲T710 虎贲T710采用8核CPU架构 xff0c 由4颗2 0GHz的Arm Cortex A75及4颗1 8GH
  • stm32 将int转换成char[]

    int a int i 61 0 j 61 0 char b 61 char a u8 c 4 for i 61 4 i gt 61 0 c j 43 43 61 b i 进行倒序 xff0c 不然显示出来是反的 xff1b USART1W
  • rabbitmq_management

    rabbitmq management是管理后台的插件 我们要开启这个插件才能通过浏览器访问登录页面 进入到sbin目录下 xff1a rabbitmq plugins enable rabbitmq management 开启服务 xff
  • freeRTOS调度

    freeRTOS调度策略 背景 嵌入式的设备开发通常有两种模式 xff1a 裸机开发和OS开发 像功能较为强大的SOC通常都会先一直linux或其他OS然后进行业务逻辑的开发 xff1b 而单片机则有很多简单的应用场景直接使用裸机开发的模式
  • 给树莓派安装Ubuntu mate(20.04LTS)并安装ROS(noetic)

    1 准备好基础的硬件设施 xff0c 然后去下载Ubuntu mate的镜像Ubuntu mate并烧录 PS xff1a 来自2022 7 8的我对曾经帖子的吐槽 xff0c 当时不知道装ROS有小鱼的一键安装 xff0c 如果安装到RO
  • VScode结合docker的ROS开发环境配置

    目录 软件安装VSCODEdocker docker image构建与运行VSCODE配置ROS插件配置clangd配置 软件安装 VSCODE 存在三种安装方式 xff0c 如下 xff1a 在vscode官网下载需要的版本直接进行安装
  • 李开复辞职前后的故事

    这些故事出自即将发售的 世界因你不同 xff1a 李开复自传 一书 xff0c 由李开复本人和北京青年报记者范海涛合写而成 以下为故事部分节选 xff1a 今天 xff0c 我开得很慢 xff0c 仿佛是让自己的心情在辽阔的天空下能够更加安
  • Gazebo仿真环境加载模型错误,卡在启动页面:Spawn service failed. Exiting 解决办法

    编写的功能包加载的世界模型文件路径如下 xff1a ganahe 64 ganahe Nitro AN515 51 catkin ws src autoNav uav ganahe models pwd home ganahe catkin
  • 集成sdk的正确姿势

    其实集成sdk很简单 xff0c 但是大部分人都有过集成sdk的经历 xff0c 而且一般都很痛苦 因为sdk分很多 xff0c 百度地图sdk xff0c 付费sdk xff0c 分享sdk等等 下面就介绍 一下本人集成sdk的一些技巧
  • http协议简析及C++实现HTTP请求

    http是超文本传输协议 xff0c 无状态协议 不同批次无法相互识别 xff0c 无连接协议 xff0c 工作在应用层 xff0c 用于完成从万维网服务器传输超文本到本地浏览器的传输协议 xff0c 完成了文档的快速传输 xff0c 还能
  • Error: Can‘t resolve ‘fs‘ in (Webpack 5.72.0)

    具体报错 xff1a ERROR in node modules handlebars lib index js 17 11 24 Module not found Error Can 39 t resolve 39 fs 39 in 39
  • 步进电机和伺服电机优缺点

    步进电机和伺服电机优缺点 步进电机和伺服电机优 缺点 xff1a 1 低频特性 步进电机在低速运行时会出现低频振动现象 xff0c 电机运行平稳性略逊于伺服电机 交流伺服电机运转非常平稳 xff0c 即使在低速时也不会出现振动现象 2 矩频
  • 十一种通用滤波算法

    十一种通用滤波算法 1 限幅滤波法 又称程序判断滤波法 A 方法 xff1a 根据经验判断 xff0c 确定两次采样允许的最大偏差值 设为A 每次检测到新值时判断 xff1a 如果本次值与上次值之差 lt 61 A xff0c 则本次值有效
  • HALCON:Optical Flow(光流法)

    HALCON xff1a Optical Flow xff08 光流法 xff09 光流法基本原理 光流概念由 Gibson 在 1950 年首先提出来 xff0c 它是一种简单实用的图像运动表达方式 xff0c 通常定义为一个图像序列中图
  • docker-环境搭建

    环境搭建 http www dockone io article 9120 https blog csdn net cloud xy article details 52470265 Docker版本 docker版本分为docker ee
  • 接口测试工具Postman接口测试图文教程

    Postman接口测试工具使用 一 前言 在前后端分离开发时 xff0c 后端工作人员完成系统接口开发后 xff0c 需要与前端人员对接 xff0c 测试调试接口 xff0c 验证接口的正确性可用性 而这要求前端开发进度和后端进度保持基本一
  • 内存的静态分配和动态分配的区别

    内存的静态分配和动态分配的区别主要是两个 xff1a 一是时间不同 静态分配发生在程序编译和连接的时候 动态分配则发生在程序调入和执行的时候 二是空间不同 堆都是动态分配的 xff0c 没有静态分配的堆 栈有2种分配方式 xff1a 静态分