首页 > 技术文章 > 堆(stack)和栈(heap)

ideaWorks 2021-12-14 20:50 原文

       先说一下,很多情况下说的堆栈其实只是指的栈,这在很大程度上误导了大家。要值得注意的是堆和栈其实完全不是一个概念。堆是堆,栈是栈,这是它们作为存储区而负责不同功能实现划分的。首先共同点是它们都存在于内存ram中,指的都是连续的存储区域。程序中的静态变量、全局变量,以及一些开辟的内存空间(malloc函数分配的内存空间)都在堆中,而对于其他的,例如局部变量、一些函数嵌套的返回地址,寄存器的值都在栈中,此外数据在栈中完成数据存放是全靠堆栈指针实现的(SP),具体操作就是采用后进先出的原则来进行压栈和出栈(PUSH and PULL),正是由于不断的操作,栈在整个程序运行中是不断变化的,就好像涨落的潮水一样。

       再来看下下面这幅图,栈和堆是使用同一端存储器空间,堆在上面,栈在下面(这个要看具体的处理器,不同处理器可能就不太一样),堆从低地址往高地址生长,栈则是从高地址往低地址方向生长,所以这时候就会出现一个问题,势必一直这样下去,必然会引起冲突,就是堆和栈争夺存储空间,这时候就会产生堆栈溢出的错误。

 

 

      在单片机编程或其他语言编程里,这是一种非常严重的错误。很可能是由于不好的编程习惯导致的,比方说,全局变量,我也不知道用多少个,上来就是1000个int型的,或者局部变量,开个数组,多大,给个500个,对于一些内存大些的还可能不出错,但一直这种编程思维肯定要犯错的。而且有时候堆栈溢出还会导致一系列其他错误。

      最后说到自己实际的踩坑,在一次32单片机编程里,调试时就出现了这个硬件错误这个提示,然后怎么会硬件错误呢,一查是用户错误上访导致的,原因是试图切换ARM状态,不急,继续追究,看到CM3书中写到入栈时的PSR寄存器的值在异常处理过程中被破坏会使得在返回时内核尝试进入ARM状态,问题定位入栈问题,在思考下肯定是发生了堆栈溢出,最后看下程序,主函数中定义了800个u16类型的变量,问题终于找到。

推荐阅读