一、前言

关于堆栈的定义在此就不赘述,详细内容可以看这篇博客。

堆栈溢出会导致野指针,返回地址错误等问题,通常程序已经无法正常运行,进入 HardFault 异常中断。为了避免这种情况,一般会分配较大的空间用做栈,可是如果仅仅为了安全就分配大空间的栈势必导致内存浪费。本文介绍两种获取栈最大消耗的方法,以方便合理设置栈的大小。

二、方法

1、方法一

栈指针 SP 指向的位置可以反应出当前栈的消耗量。在 STM32 中,栈是向下生长的,如果我们定期的获取栈指针 SP 的值,比较后得到一个最小值,就代表了栈的最大消耗量。而如何才能定期去获取栈指针 SP 的值呢?可以使用定时器产生一个周期性的中断,在中段函数中获取栈指针 SP 的值。最简单的方法就是在系统滴答定时器(SysTick)的中断函数中调用栈分析函数。具体可以参看如下的函数。在程序运行结束后,再去获取最大栈消耗量。

static uint32_t max_stack_usage = 0xffffffff;

void stack_parse()

{

int a = 0;

if((uint32_t)&a < max_stack_usage)

{

max_stack_usage = (uint32_t)&a;

}

}

uint32_t get_max_stack_usage()

{

return max_stack_usage;

}

由于这个函数是周期执行的,必然对程序的运行性能产生影响,不过这只是为了分析,最终是要移除的。另外由于是周期执行,所以可能会错过一些周期性的压栈,以至于获取的数值并不是最大值。不过,这种方法还是有它的参考意义的。

2、方法二

在 IAR 中,可以开启栈使用分析(IAR Embedded Workbench Stack Usage Analysis),让 IDE 在编译链接阶段就推算出这个程序的栈最大使用量。不过这种方法无法分析使用函数指针的方式调用的函数,也不能确定递归函数的嵌套次数,因此这两种情况下需要使用配置文件来指出这种调用的压栈空间,比较麻烦,具体可看官方手册。不过函数指针和递归函数毕竟是少数情况,大多数的函数都是显示调用的。因此 IDE 会分析出一条最长的调用路径,从而分析出最大的栈使用量。步骤如下:

1、开启 options > linker >Advanced > Enable stack usage analysis

2、编译后查看 map 文件中的 STACK USAGE 部分

内容类似于:

*******************************************************************************

*** STACK USAGE

***

Call Graph Root Category  Max Use  Total Use

------------------------  -------  ---------

Program entry              8 600      8 600

Uncalled function            256      1 332

三、总结

栈空间用来存放局部变量,部分函数参数,返回地址,以及保存函数调用时主调函数的寄存器内容等。为了减少栈的分配,一定要注意不要在函数中放置很大的局部数组。上文所需的 8600 字节的栈空间,就是因为程序中有一个函数中分配了一个 8192 字节的数组,如下。

int decode_subframe_lpc(FLACContext *s, int32_t* decoded, int pred_order)

{

int sum, i, j;

int64_t wsum;

int coeff_prec, qlevel;

int coeffs[2048]; //8k, use heap to save stack

int32_t* output;

int32_t* reader;

int* pcoeffs;

...

}

可以使用两种方式来修改。其一,将 coeffs 这个数据变成 static 局部静态变量,这样做可以将这个变量从栈中移到 .bss 区域中,不过这种方式并不灵活,相当于 8192 B 的空间被占用,而其他函数无法使用。所以本质上和放在栈空间中区别不大。其二是通过 malloc 的方式灵活申请和释放内存,当不在需要这部分空间时,可以将其释放。

iar 堆栈设置_IAR开发STM32堆栈设置相关推荐

  1. 在ubuntu下设置eclipse开发STM32等嵌入式设备

    之前为了能够让ROS与底层能够顺利通讯,我采用可开源开发板arduino ,因为arduino有ROS的库,能够按照ROS wiki上所给的教程就可以顺利的开发,但由于arduino的局限性,我觉得是 ...

  2. android输入法开发 设置,Android开发随手记录-设置输入法触发

    登录界面 上面是我开发的一个app中的登录页面,比较典型,可以使用账号登录,也可以用第三方平台授权登录,我们一般会要求用户输入账号密码,然后点击登录按钮进行登录,但有时候用户可能点不到登录按钮,输入法 ...

  3. iar 堆栈设置_IAR MSP430设置合理堆栈大小(the stack pointer for stack is outside the stack range)...

    摘要: 本文给出IAR设置堆栈合理大小的详细方法,并分享一些好博文(icf及map讲解). 最近在MSP430-169LCD(MSP430F169,RAM为2KB)调试一些ucos演示例子,IAR f ...

  4. 在IAR下如何查看工程的堆栈(STM32)

    在IAR下编程,难免少不了要跟堆栈打交道,但是打交道之前也要知道堆栈的大小,以及堆栈的位置在哪里? Options->Linker->Overridde default->Edit查 ...

  5. 设置c++程序的堆栈空间解决栈溢出问题

    设置c++程序的堆栈空间解决栈溢出问题 程序的静态数据量大的时候,有时候会出现栈溢出问题,往往是程序还没运行算法呢,就down掉了,比如你在创建包含大数组的类(或数据)的时候,栈就溢出了.这是由于系统 ...

  6. 【Android 应用开发】Activity 返回堆栈清除操作 ( 默认状态 | 清除返回堆栈配置 | 不清除返回堆栈配置 | 清除指定界面配置 )

    文章目录 I . 返回堆栈 默认操作 II . 返回堆栈 保留所有元素操作 III . 返回堆栈 清除除根元素外所有元素操作 IV . 返回堆栈 清除指定的 Activity V . 总结 I . 返 ...

  7. STM32 堆栈溢出检测

    前言 在单片机中,栈stack由编译器自动分配释放,用于存放函数调用,局部变量等数据.堆heap用于动态内存分配.堆栈可以在启动文件或者链接脚本中指定大小,但在实际开发中,尤其工程量较大的项目中难以确 ...

  8. 在Windows上设置CloudStack开发环境

    1)安装 Cygwin. Cygwin 可以为你的windows提供一个类似Unix 的bash shell 环境. 下载并安装Cygwin请使用 setup.exe. 设置 Cygwin 安装路径为 ...

  9. 【linux】ARM开发板上设置RTC时间,断电重启后,设置失效的原因分析

    问题描述 linux中使用date设置时间后用hwclock -w同步到RTC,断电重启后,有时会失效 原因分析 保存时间戳 1.使用命令关机(halt)会调用rc0.d中的脚本: 2.使用命令重启( ...

  10. vs2010设置boost开发环境

    1. 编译boost类库 2. 设置vs2010的环境 <1>. 编译boost类库  前面一篇文章介绍了如何在linux下建立boost的开发环境,并且编写了一个测试程序,这里将试着在w ...

最新文章

  1. sqlserver导入excel的电话号码(身份证)变为科学计数解决方式
  2. php如何批量导入题库,批量文本导入试题
  3. 关于后端java项目使用SpringBoot框架的报错总结
  4. ASP.NET Core开源Web应用程序框架ABP
  5. 编写程序,对用户输入的n个整数,统计其最大数、最小数和平均值
  6. 大数据预测实战-随机森林预测实战(三)-数据与特征对模型的影响
  7. MySQL越高版本越快吗_MySQL性能优化的最佳20+条经验
  8. 95-860-040-源码-定时器-SystemProcessingTimeService简介
  9. 推理集 —— 现象与观察
  10. C# async/await异步编程深入理解
  11. Linux内核学习笔记一
  12. 淘淘商城第27讲——实现图片上传功能
  13. RestClient操作索引库
  14. 机器学习之逻辑回归(Logistic Regression)
  15. 三节锂电池充电芯片,IC设计模块的几种电路
  16. 安卓手机状态栏显示秒_让安卓手机上方状态栏时间显示精确到秒方法
  17. YAMLException: bad indentation of a mapping entry at line 解决
  18. python数据收集整理教案_《数据收集整理》教学设计
  19. 【Autosar vLinkGen 链接器脚本生成器】
  20. Linux内核进程调度时机和过程

热门文章

  1. Kubernetes K8S之affinity亲和性与反亲和性详解与示例
  2. [模拟] Jzoj P2499 东风谷早苗
  3. postgresql数据库 timescaledb 时序库 超级表 块的压缩(compress_chunk()的应用)
  4. android获取农历时间,android 日历(带提醒、日程、阴历转换)
  5. RFBnet论文翻译:感受野块网络对于精确的和快速的目标检测
  6. 此生未完成 --- 于娟
  7. 【python爬虫】爬取《英雄联盟》英雄及皮肤图片数据
  8. 计算机内打不开小米路由器,win7系统无法访问小米路由器的解决方法
  9. linux驱动开发(三):Linux字符设备驱动实例
  10. IAR Fatal error