当前位置:首页 > > TopSemic嵌入式
[导读]可能很多人心中都有一个武侠梦,记得小时候搬个小凳子,到邻家院子里蹭电视看,正值金庸先生的射雕英雄传热播,一伙人屏息静气,全神贯注,随着郭靖黄蓉出山入海,驰骋大漠。然后觉得自己比憨憨的郭大侠,还是要聪明一点点,于是找来布袋子,装上沙子,苦练武功。如今想来奇怪,怎么单练这铁掌帮的功夫呢?真是好坏不分,值得检讨。

可能很多人心中都有一个武侠梦,记得小时候搬个小凳子,到邻家院子里蹭电视看,正值金庸先生的射雕英雄传热播,一伙人屏息静气,全神贯注,随着郭靖黄蓉出山入海,驰骋大漠。然后觉得自己比憨憨的郭大侠,还是要聪明一点点,于是找来布袋子,装上沙子,苦练武功。如今想来奇怪,怎么单练这铁掌帮的功夫呢?真是好坏不分,值得检讨。

此去经年,武侠梦碎。没办法华山论剑,只能论一下栈了。

  1. 什么是堆栈

我们说堆栈,其实堆是堆(Heap),栈是栈(Stack)。一般我们写程序时不太关心堆栈,因为编译器会帮我们处理。但是还是有必要把它们弄清楚,不然有时候出了莫名其妙的问题,会无从下手。比如说堆栈溢出,就好比一个幽灵,非常难发现。看起来一切都挺好,程序编译运行,测试,可能都好好的,直到它突然出现,发出致命一击,导致系统崩溃。

先看一个典型的存储器示意图,编译器把RAM划分为静态存储区,堆区,栈区。静态存储区用于存放全局变量,静态变量,编译的时候它的大小也就确定了;紧挨着的是堆(Heap)区,由程序调用malloc,free等函数来分配和释放;栈区由编译器自动分配和释放,用来传递参数,存放局部变量等。栈比较特殊,正常情况下,它是后进先出的。

栈的使用是从高地址,也就是Top of Stack开始,向下增长。

那为什么要把局部变量分配在栈里呢?因为单片机访问栈用的指令,和访问全局变量区域用的指令是不一样的,访问栈的指令速度更快。再一个就是这些局部变量,只有所在函数被调用的时候才会分配,函数返回时分配的空间就被收回了,不像全局变量始终占用内存。

我们看一个程序,用到了比较多种类的变量类型。

编译后的map文件:

我们可以看到全局变量,还有静态局部变量都放到了静态存储区。非静态的局部变量在map文件是找不到的。

特别关注一下P1这个指针型变量,因为它是全局变量,所以变量本身分配在静态存储区,但是它指向的用Malloc申请的内存,是在堆区。如下图:

  1. 堆栈溢出

堆栈溢出,主要是指栈溢出。因为我们在堆中,用malloc, 或new函数申请内存时,如果空间不够了,函数会返回NULL,很清楚它的空间不够了。而栈由于是函数调用时分配,占用空间大小跟调用深度有关,编译器很难确定最大需要多少空间。如果栈空间过小,直接的结果就是当栈增长超过栈底,堆中的数据,甚至是静态存储区数据被冲掉,导致不可预知后果。

那怎么避免堆栈溢出,至少知道发生了堆栈溢出呢?

一个就是在启动文件里,把堆栈的值尽量改大。编译的时候用 –info=stack可以大概看一下,各个函数占用栈的大小。

综合编译后RAM剩余空间的大大小,可以直接把栈空间放到最大。在下面的源文件中可以直接修改堆和栈的大小。对于静态存储空间,编译器会根据实际使用大小进行分配,我们不用关心。

还有一个方法,在栈底放置特殊字符,然后在程序运行过程中,监测特殊字符是否被更改,如果被更改,大概率是发生了栈溢出,此时可以采取一定的补救措施。如何操作呢?先在启动文件用EXPORT Stack_Mem导出栈底,在主程序定义同名外部函数extern void Stack_Mem(void); 然后就可以往栈底写入数据了,参见前面的程序。

这种方法的缺点就是,跑飞了的野指针,也可能篡改这一区域数据,造成误判。还有一个就是,因为做数据比较判断,要消耗CPU时间,一般只能周期性检测,在没检测出问题之前,栈溢出有可能已经造成程序出问题了。你用过更好的方法吗?欢迎一起来探讨。


本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

Aug. 6, 2025 ---- 根据TrendForce集邦咨询最新调查,因国际形势变化以及中国相关政策的推动,2025年上半年全球电视品牌出货量达9,250万台,年增2%。由于品牌普遍提前出货,下半年旺季可能面临压...

关键字: LED OLED 电视

April, 16, 2025 ---- 根据TrendForce集邦咨询最新研究,OLED显示技术持续发展,带动QD-OLED显示器(monitor)出货量成长,预计在OLED显示器的占比将从2024年68%提升至20...

关键字: OLED 显示器 电视

April 1, 2025 ---- 乐金显示广州LCD 8.5代线今日(4月1日)正式交割至TCL华星光电,并改名为t11。至此,TCL华星光电将拥有2条6代、4条8.5代、1条8.6代和2条10.5代LCD产线。Tr...

关键字: 电视 PID面板 LCD

随着科技的飞速发展,人工智能(AI)已经渗透到我们生活的方方面面,尤其在电视领域,其革新性的影响更是引人瞩目。近日,据韩媒MK的报道,全球电视市场的领军企业三星,正与OpenAI达成合作,共同开发AI电视,这无疑为我们揭...

关键字: 三星 OpenAI 电视 AI

12月5日消息,根据洛图科技发布的《中国电视市场品牌出货月度快报》显示,11月在“双十一大促”和“以旧换新”国补下,终端销售的产品结构得到了大幅改善,超大尺寸、Mini LED、高能效产品热卖。

关键字: 电视 OLED

Aug. 27 ---- 根据TrendForce集邦咨询最新调查,2024年上半年全球电视品牌出货量达9,071.7万台,年增0.8%。各地区需求表现不一,中国因房地产市场因素及年轻人使用习惯改变,电视销售不如预期。相...

关键字: 电视 OLED

在现代电子设备中,屏幕是我们与之互动的主要界面。无论是智能手机、电视还是显示器,选择LCD还是OLED屏幕都有其独特的优点和缺点。以下是关于这两种技术的详细比较,以帮助您做出明智的选择。

关键字: 电子设备 智能手机 电视

Feb. 1, 2024 ---- 据TrendForce集邦咨询研究显示,2023年全球电视出货量约1.95亿台,年减2.7%,创近十年来新低。观察2024年,第一季适逢传统消费淡季,预估全球电视出货量季减约18.9%...

关键字: 电视 面板

LCD屏幕和LED屏幕是常见的显示技术,用于电视、电脑显示器和移动设备等。本文将详细介绍LCD屏幕和LED屏幕的区别,包括工作原理、亮度、对比度、能效、颜色表现、尺寸和价格等方面的对比。

关键字: lcd屏 oled屏 电视

Jan. 3, 2024 ---- 2023年全球电视需求持续受到通胀影响,在消费者可支配所得有限的情况下,高价商品即便降价促销也难刺激买气,导致以中高阶机种为销售主力的国际品牌出货呈现衰退。据TrendForce集邦咨...

关键字: 电视 供应链 TCL
关闭