0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

关于堆栈的深入理解

0BFC_eet_china 来源:未知 作者:邓佳佳 2018-03-04 15:57 次阅读

一、这些个概念怎么来的以及怎么记得住

这里,只限于整理我个人对堆/栈/堆栈在内存管理方面的理解。其他,在数据结构方面讲的堆/栈目前不在我整理范围之内。

这里提了三个概念: 堆,栈,以及堆栈。我把栈和堆栈的概念等同了。所以,接下来只要把两个概念弄清楚就可以了:堆和栈。

先说由来。由于我的工作大部分是和单片机相关的,因此也是基于嵌入式的这个方面的理解。

每片MCU有一定的内存,这些内存分:程序存储区;数据存储区。举例就是:我们写的每行代码,都会保存到程序存储区里面;而定义的一些全局变量,静态变量,局部变量之类的,就保存到数据存储区。

程序存储区,对于写代码的人来说,可以说是黑盒子:只要你的代码不超过程序代码空间,everything will be fine. 代码究竟是如何执行的,取决于你的编程思想,就是说,你让程序往东走,它就会往东走;让它原地踏步,它也会照做;前提是你的代码要写好。所以,对于编程经 验成熟的人,同样的算法,他可能会少敲几行代码,并且算法出错的几率少一些;不怎么会编程的人,就多敲几行,多测试一下。研究深一些的人,可能还会对代码 执行效率深入研究。我决定就此止步。继续黑盒子的话题程序员的代码会烧写到程序存储区里面,至于哪条语句存哪里,这个是不用研究的。反正,一旦发现软件 没按照你设计的那样跑,基本就是程序自身的问题,不是存放程序的存储区的问题。

数据存储区,让程序员发挥的空间就很大了。由于程序是动态地执行的,执行的结果是怎么样,会产生什么数据就不是一个确定的事情。

举个例子说说这个程序和数据之间的表象吧。举例的事件就是:一个MP3播放器的上/下键的操作。加入在播放器里有10首歌,若当前是第3首,那 么按下[上]键后,应该是播放第2首。因此,实现播放第2首的,就是程序员写程序实现的,他的代码让[上]键实现了能从第3首切换到第2首的操作。这里, 表现的就是代码。而且,这个代码是确切的行为,从第3首按了[上]键之后,一定是播放到第2首。这个是确切的行为,如果不能实现,就是代码有bug了,需 要改正。终于可以扯到数据了。第2首是什么歌呢? 就是说第2首歌的内容是什么呢? 当然在程序员写代码的时候,他是不知道的,他要做的,就是预先开一片数据空间,以存放歌曲相关的数据。这片数据空间,想放什么就放什么,是灵活的。听烦了 这几首歌以后,再更换其它音频文件就是了。再说具体一点,程序就相当于修的一条路,让车可以在上面跑;但车上面装了什么,程序员是不知道的。

堆和栈属于数据存储区的范畴,也可以算是数据管理的手段或方法。基于此,不能一概而论,说哪个手段高明一些;他们也是基于现实的需要而产生的。黑格尔说:存在就是合理的。

这样的概念大家都不陌生:军队的管理是很严格的,很死板的;但是对于一些年轻的技术公司来说,员工就享有很高的自由度。

如果我说,墙角边整齐地摆放着10本书; 以及墙角边的书凌乱地放着。你闭上眼睛,能区分出两种画面吗? 如果没有,就不用往下看了。

栈的特性,就是严格/有序/规范的。栈的英文就是Stack. 如果我说,there are books stacked in that corner,你应该能知道书是怎么放的吧。

相反,堆呢,就是自由/灵活/随意的。堆的英文是Heap. 如果我说,there are books heaped in that corner,你应该能知道书是怎么放的吧。

二、get closer to the real STACK/HEAP。

栈: 由系统自动分配和回收的。

堆: 由程序员分配和回收的。

基于第一部分的理解,不用想都知道,作为“堆”的数据空间,也必须是灵活的,因为成千上万的程序员在写什么程序是未知的。但可知道的一点,就是他们是跑在确定的某个OS里面的。

因此,也不过就是给系统管理的数据空间起了个名字,就栈;给程序员使用的空间,起了个名,就堆。

我接下来就会废话:起什么名字都不重要,重要的是,我们得对这两种数据存储区的管理的机制由来,方法有深刻认识;这样,即便几个世纪以后它们更名为阿猫阿狗了,我们依然能认知它们。

举例:

void Check_Pro_Code( uint8 style )

{

uint8 i;

switch( style )

{

......

}

}

void main( )

{

uint8 j = 1;

Check_Pro_Code( j );

}

在main()函数里调用了Check_Pro_Code(...)函数,事先要对j进行入栈操作;当然这里函数调用的时候,涉及到几个入栈操作:程序的下一个执行地址;局部变量;形参。

这里,我就没有深入介绍了。

实在很惭愧的是,我写的嵌入式软件里,没有涉及到任何和堆操作相关的。我就是那样一个人,CM3内核里也没有移植操作系统,实在是汗颜,因为本人对RTOS实在是未曾涉猎。所以,我这里对于堆的介绍,是没有任何实战鹰眼的。并且为了堆我就堆了一下。你说,这样算学术造假吗?

void main( )

{

int j=10;

int *p;

p = malloc( 10 ); //话说这里就是堆,我是为了用而用,实在是无味地很。

p = "123456".

}

三、话说堆栈溢出

再次明确,堆栈溢出的堆栈是指栈。

1 当C程序函数的调用层次过深或者出现了递归调用,就容易使程序运行所需的堆栈空间超过系统能提供的最大堆栈空间范围,产生堆栈溢出。

这是很明白的,当A函数调用了B函数,而B()里面又调用了C(),C()里又调用了D()......当这样的调用太深的时候,就容易堆栈溢出了。

四、一级缓存/二级缓存

栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立即释放。

堆则是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。

栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器

举个我知道的例子:

void main( )

{

int i,j;

static int flag = 1;

i = Sum_Of_Group( );

j = Check_Exist( );

}

这里,i,j的值都是给通用寄存器的,而不是给予确切的物理地址。而对于flag,由于其为静态变量,是在SRAM里面分配地址的。这里好像没有说到一级缓存二级缓存。时间限制,下回述。

五、栈:在Windows下,栈是向低地址扩展的数据 结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在 WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因 此,能从栈获得的空间较小。

堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

注:该段内容100%抄袭,出处:网络

六、如何修改我自己的工程的STACK(以下内容不通用)

由于我自己的工程用的是LPC1765,刚好从网络抄到了比较有用的图片。摘于此。其他单片机的编译环境,应该也是差不多如法炮制的。

编译环境: IAR for ARM.

图一 :如何修改STACK的大小

图二,如何知道自己的工程用了多少堆栈

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 堆栈
    +关注

    关注

    0

    文章

    182

    浏览量

    19894

原文标题:关于堆栈的深入理解

文章出处:【微信号:eet-china,微信公众号:电子工程专辑】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    深入理解C语言:循环语句的应用与优化技巧

    能让你的代码更加简洁明了,还能显著提升程序执行效率。本文将详细介绍C语言中的三种常见循环结构——while循环、for循环和do...while循环,带你深入理解
    的头像 发表于 12-07 01:11 332次阅读
    <b class='flag-5'>深入理解</b>C语言:循环语句的应用与优化技巧

    深入理解 Llama 3 的架构设计

    最新的自然语言处理(NLP)技术和深度学习算法,旨在提供更加自然、流畅和智能的对话体验。 1. 核心组件 Llama 3的架构设计可以分为以下几个核心组件: 1.1 预处理模块 预处理模块负责将原始文本数据转换为模型可以理解的格式。这包括文本清洗
    的头像 发表于 10-27 14:41 770次阅读

    深入理解FPD-link III ADAS解串器HUB产品

    电子发烧友网站提供《深入理解FPD-link III ADAS解串器HUB产品.pdf》资料免费下载
    发表于 09-06 09:58 1次下载
    <b class='flag-5'>深入理解</b>FPD-link III ADAS解串器HUB产品

    堆栈和内存的基本知识

    本文主要聊聊关于堆栈的内容。包括堆栈和内存的基本知识。常见和堆栈相关的 bug,如栈溢出,内存泄漏,堆内存分配失败等。后面介绍软件中堆栈统计
    的头像 发表于 08-29 14:10 655次阅读
    <b class='flag-5'>堆栈</b>和内存的基本知识

    如何理解LC表和选择关于TPS563202的LC

    电子发烧友网站提供《如何理解LC表和选择关于TPS563202的LC.pdf》资料免费下载
    发表于 08-26 10:02 0次下载
    如何<b class='flag-5'>理解</b>LC表和选择<b class='flag-5'>关于</b>TPS563202的LC

    锡焊原理解析:深入理解电子产品制造的核心工艺

    探索焊接技术在精密电子工程中的重要性和创新,从基础元件的连接到现代焊接技术的进展,深入了解焊接材料的选择与焊接技术的分类。本文提供了对锡焊原理的深入分析,揭示了高质量电子产品制造的关键因素。
    的头像 发表于 08-12 15:03 971次阅读
    锡焊原<b class='flag-5'>理解</b>析:<b class='flag-5'>深入理解</b>电子产品制造的核心工艺

    揭秘LED灯带功率:深入理解每米功率的科学

    在现代照明设计中,LED灯带以其灵活性和节能特性,成为营造室内氛围的重要工具。本文将深入探讨LED灯带的功率选择,提供实用的技术指导,帮助读者根据自身需求选择合适的灯带。
    的头像 发表于 08-03 15:45 2845次阅读

    技术干货驿站 ▏深入理解C语言:基本数据类型和变量

    在C语言中,数据类型和变量是编程的基础,也是理解更复杂概念的关键。数据类型决定了变量的内存分配、存储范围和操作方式,而变量则是存储数据的容器。本篇文章将从基本数据类型和变量两个方面,带你深入了解C
    的头像 发表于 07-26 17:53 2357次阅读
    技术干货驿站 ▏<b class='flag-5'>深入理解</b>C语言:基本数据类型和变量

    深入理解渲染引擎:打造逼真图像的关键

    在数字世界中,图像渲染是创造逼真视觉效果的核心技术。渲染引擎,作为这一过程中的关键组件,负责将二维或三维的模型、纹理、光照等数据转化为人们肉眼可见的二维图像。本文将深入探讨渲染引擎的工作原理及其在打
    的头像 发表于 06-29 08:28 442次阅读
    <b class='flag-5'>深入理解</b>渲染引擎:打造逼真图像的关键

    深入理解FFmpeg阅读体验》FFmpeg摄像头测试

    零、前期工作 上文FFmpeg移植完成后,需要将x264/lib文件夹下的库文件拷贝到开发板的/lib/目录下,将ffmpeg_install/lib文件夹下的库文件全部拷贝到开发板的/lib/目录下,将ffmpeg_install/bin/目录下的ffmpeg文件拷贝到开发板的/bin/目录下。 root@myd-yd9x:~# df -h Filesystem SizeUsed Available Use% Mounted on /dev/root1.9G1.9G0 100% / devtmpfs 619.1M0 619.1M0% /dev tmpfs 763.8M0 763.8M0% /dev/shm tmpfs 763.8M 184.0K 763.7M0% /tmp tmpfs 763.8M 468.0K 763.4M0% /run 然后测试下ffmpeg: root@myd-yd9x:/bin# ./ffmpeg ffmpeg version N-114829-gf48987f609 Copyright (c) 2000-2024 the FFmpeg developers built with gcc 7.3.1 (Linaro GCC 7.3-2018.05) 20180425 [linaro-7.3-2018.05 revision d29120a424ecfbc167ef90065c0eeb7f91977701] configuration: --prefix=/home/ffmpeg_install --enable-cross-compile --arch=arm64 --target-os=linux --cc=aarch64-linux-gnu-gcc --disable-x86asm --cross-prefix=aarch64-linux-gnu- --pkg-config=/usr/bin/pkg-config libavutil59. 15.100 / 59. 15.100 libavcodec61.5.103 / 61.5.103 libavformat 61.3.100 / 61.3.100 libavdevice 61.2.100 / 61.2.100 libavfilter 10.2.101 / 10.2.101 libswscale8.2.100 /8.2.100 libswresample5.2.100 /5.2.100 Universal media converter usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}... Use -h to get full help or, even better, run \'man ffmpeg\' OK的。 二、连接摄像头 我用的是手头的海康720P USB摄像头。 插进去后系统自动识别。 [ 1812.860609] uvcvideo: Found UVC 1.00 device HIK 720P Camera (2bdf:0280) [ 1812.863363] uvcvideo 1-1.5:1.0: Entity type for entity Extension 3 was not initialized! [ 1812.863439] uvcvideo 1-1.5:1.0: Entity type for entity Processing 2 was not initialized! [ 1812.863505] uvcvideo 1-1.5:1.0: Entity type for entity Camera 1 was not initialized! [ 1812.865476] input: HIK 720P Camera: HIK 720P Camer as /devices/platform/soc/soc:usb3@31260000/31260000.dwc3/xhci-hcd.0.auto/usb1/1-1/1-1.5/1-1.5:1.0/input/input4 [ 1812.869972] snd-usb-audio 1-1.5:1.2: no of_node; not parsing pinctrl DT 然后在/dev中发现了video8设备,记住名字备用。 三、视频录制 通过FFmpeg录制视频使用如下cmd: ffmpeg -f video4linux2 -s 320x240 -i /dev/video8 /tmp/cam_video.avi 看看CPU占用率。 将视频拷贝出来,因为录制的时候分辨率没设置很高,所以将就看看,能看出是啥电影吗?
    发表于 04-17 19:06

    深入理解FFmpeg阅读体验》

    一、编译X264 H.264是ITU(International Telecommunication Union,国际通信联盟)和MPEG(Motion Picture Experts Group,运动图像专家组)联合制定的视频编码标准。而X264是一个开源的H.264/MPEG-4 AVC视频编码函数库,是最好的有损视频编码器之一。 先直接从网络(http://download.videolan.org/pub/videolan/x264/snapshots/)获取X264源码。考虑到版本关系,本文我下载的是x264-snapshot-20180430-2245-stable.tar.bz2。 tar -vxf x264-snapshot-20180430-2245-stable.tar.bz2 mkdir x264 手动创建的X264文件夹用于存放编译后的X264库。执行如下命令: ./configure --host=aarch64-linux --prefix=/home/x264 --enable-shared --disable-asm --enable-static --cross-prefix=aarch64-linux-gnu- 之后执行make make install完成x264库的交叉编译。生成的文件信息如下: root@EliteDesk800:~/x264/lib$ ls libx264.solibx264.so.152pkgconfig root@EliteDesk800:~/x264/lib$ file * libx264.so:symbolic link to libx264.so.152 libx264.so.152: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, BuildID[sha1]=01dd733d65c98eb894b4cdd41216259543ec8405, with debug_info, not stripped pkgconfig:directory 二、编译FFmpeg 首先从FFmpeg官方网站http://ffmpeg.org/download.html上下载FFmpeg源码。 tar -vxf ffmpeg-snapshot.tar.bz2 mkdir ffmpeg_install 其中ffmpeg_install文件夹用于保存生成的文件。执行如下命令: ./configure --prefix=/home/ffmpeg_install --enable-cross-compile --arch=arm64 --target-os=linux --cc=aarch64-linux-gnu-gcc --disable-x86asm --cross-prefix=aarch64-linugnu---pkg-config=/usr/bin/pkg-config --pkg-config=/usr/bin/pkg-config主要用于解决ERROR: x264 not found using pkg-config问题,网上很多解决方法都不靠谱。 之后执行make make install完成ffmpeg的交叉编译。 生成的文件信息如下: root@EliteDesk800:~/ffmpeg$ file ../ffmpeg_install/bin/* ../ffmpeg_install/bin/ffmpeg:ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, BuildID[sha1]=b32285f11866f79dd499330849a9b3195ea0e446, stripped ../ffmpeg_install/bin/ffprobe: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, BuildID[sha1]=5d3fa4ea21ad6c4395bbaf134b915190799305b2, stripped
    发表于 04-16 22:54

    深入理解 Sora 的技术原理

    将去除噪音后的结果数据,利用视频解码器进行解码,将低维潜在空间数据还原成原始视频数据,这里可以实现不同分辨率的视频解码。
    的头像 发表于 04-05 09:19 2079次阅读
    <b class='flag-5'>深入理解</b> Sora 的技术原理

    深入理解 FPGA 的基础结构

    转载地址:https://zhuanlan.zhihu.com/p/506828648 文章很详细的介绍了FPGA的基础结构,能更直观的理解内部结构原理。对深入学习很有帮助。 以下是正文: 这一段
    发表于 04-03 17:39

    深入理解Linux网络协议

    网络分层解决了网络复杂的问题,在网络中传输数据中,我们对不同设备之间的传输数据的格式,需要定义一个数据标准,所以就有了网络协议。
    发表于 04-01 14:20 469次阅读
    <b class='flag-5'>深入理解</b>Linux网络协议

    深入理解数据备份的关键原则:应用一致性与崩溃一致性的区别

    深入理解数据备份的关键原则:应用一致性与崩溃一致性的区别 在数字化时代,数据备份成为了企业信息安全的核心环节。但在备份过程中,两个关键概念——应用一致性和崩溃一致性,常常被误解或混淆。本文旨在阐明
    的头像 发表于 03-11 11:29 1101次阅读
    <b class='flag-5'>深入理解</b>数据备份的关键原则:应用一致性与崩溃一致性的区别