搜索
bottom↓
回复: 3

IAR 如何判断堆空间的使用情况?

[复制链接]

出0入0汤圆

发表于 2019-1-18 16:15:47 | 显示全部楼层 |阅读模式
单片机使用了C++,堆溢出是个比较麻烦的问题,现在好了,

堆栈的概念在脑海里已经存在有一段时间了,今天就测试来整理下Heap堆。栈以后再说。

堆区不像全局变量和局部变量总是有指定的内存大小,它是为了在程序运行时动态分配内存而设定的一块区域。

在程序运行时需要一块特定大小的内存空间来使用的时候,那么可以先声明空间大小值,然后在程序运行时会在某个区域里划分指定大小的内存空间出来,这里所说的某个区域就是堆区。

堆内存通常用类似malloc,free的函数来分配内存大小和释放内存。

Malloc函数用来动态分配堆内存空间。成功分配空间后返回分配的内存地址指针。如果申请分配的空间大小大于堆的大小就返回NULL。

Free函数用来释放先前分配的空间(创建堆空间后一定要记得释放)。

动态分配内存的时候由于存在内存指针和内存大小的关系,可能会导致overhead,反复分配和注销空间的话也会发生fragment问题.

实现动态分配内存的方法有很多种,在IAR Compiler里使用最多的是dlmalloc方法。

想要了解更多关于动态分配内存的可以点这里C dynamic memory allocation

看下面的例子

我们设定Heap的大小为512Byte,然后申请分配461byte空间。结果我们可以看到因为无法分配461Byte的空间导致返回NULL.

因为overhead导致最大只能使用460byte空间。

另外,由于overhead的原因,与一次性分配大空间内存相比,分多次来分配小一点内存空间,反而使我们能够使用的总内存空间更少。

下面的例子是每次分配10byte,结果第30次的时候就无法再分配内存了。计算一下总共也只分配了290byte。

而在第一个例子里一次性分配大内存空间的时候最多反而可以分配460byte。

综上所说与多次分配小内存相比,一次性分配大内存方式使得能使用的最大heap空间更多。

在写嵌入式程序的时候,不像PC上内存资源丰富,嵌入式板子内存资源有限,必须准确的分配好heap堆的空间大小。然后预测一个程序要使用多少的heap空间,需要分配多大的heap并不是一件容易的事。

IAR EWARM提供能够查询堆使用量的函数。利用提供的函数我们就可以预测程序大概需要多大的heap空间。

下面介绍部分动态分配内存相关的库函数

在使用IAR提供的库函数之前需要进行下面的操作

在项目中添加IAR EWARM安装目录下的​arm\src\lib\dlmalloc.c文件

NO_MALLINFO 设置为 0

NO_MALLOC_STATS设置为0

1. __iar_dlmalloc_stats

标准输出(stdout)heap空间总大小以及heap使用量。

2. __iar_dlmallinfo

返回包含heap大小以及使用情况的结构体。

    Mallinfo结构体信息参照下面内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
       
#if !NO_MALLINFO
/*
  mallinfo()
  Returns (by copy) a struct containing various summary statistics:
  
  arena:     current total non-mmapped bytes allocated from system
  ordblks:   the number of free chunks
  smblks:    always zero.
  hblks:     current number of mmapped regions
  hblkhd:    total bytes held in mmapped regions
  usmblks:   the maximum total allocated space. This will be greater
                than current total if trimming has occurred.
  fsmblks:   always zero
  uordblks:  current total allocated space (normal or mmapped)
  fordblks:  total free space
  keepcost:  the maximum number of bytes that could ideally be released
               back to system via malloc_trim. ("ideally" means that
               it ignores page restrictions etc.)
  
  Because these fields are ints, but internal bookkeeping may
  be kept as longs, the reported values may wrap around zero and
  thus be inaccurate.
*/
struct mallinfo dlmallinfo(void);
#endif /* NO_MALLINFO */

更改heap堆大小

依照下面的方式可以设置使用heap堆的大小。

Heap堆大小在项目option的Linker选项里设置。

在Linker的Config里 点击Edit来变更Linker的设置。

在Stack/Heap Sizes选项卡里变更heap堆大小。

分配的heap堆大小可以再map文件里查看确认。

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2019-1-18 18:40:52 来自手机 | 显示全部楼层
嵌入式用堆不怕内存碎片么

出0入0汤圆

 楼主| 发表于 2019-1-29 09:43:58 | 显示全部楼层
大傻师 发表于 2019-1-18 18:40
嵌入式用堆不怕内存碎片么

我们的项目要用嵌入式C++.如果底层的函数可以改成自定义的内存管理函数的话自然是最好的了。

出0入362汤圆

发表于 2019-1-29 10:42:55 | 显示全部楼层
iar不知道
gcc的话只要把_sbrk(0)和MSP指针的值printf到串口就知道了, _sbrk(0)是堆尾, MSP是栈顶
(使用c标准库的malloc的情况)

或者靠试运行malloc来算出剩余堆空间,二分查找,试出能成功分配内存的最大值
不过在gcc上只能得出最大的2的整数次幂值,比如实际堆空间还有7k多,用下面的方法最大能得到4096,但分配4096字节后再试,能得到2048,得到2048后还能再得1024, 估计libc里malloc就是这么设计的。
  1. static size_t __get_free_mem2(size_t start, size_t end)
  2. {
  3.     unsigned char *p;
  4.     size_t size;
  5.     while(start < end) {
  6.         size = (start + end + 1) / 2;
  7.         if(size == 0)
  8.             return 0;
  9.         p = malloc(size);
  10.         if(p != NULL) {     // malloc succeeded
  11.             free(p);
  12.             start = size;
  13.         }
  14.         else {              // malloc failed
  15.             end = size - 1;
  16.         }
  17.     }
  18.     return start;
  19. }

  20. size_t get_free_mem(void)
  21. {
  22.     return __get_free_mem2(0, 65536UL);
  23. }
复制代码
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-18 22:52

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表