搜索
bottom↓
回复: 15

求Heap的剩余空间方法,Keil + MicroLib。

[复制链接]

出0入0汤圆

发表于 2021-9-17 09:59:13 | 显示全部楼层 |阅读模式
如何获取Heap的使用信息?
好像标准库中有 __heapstats() 可以输出。
还有什么方法吗?

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

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2021-9-17 11:02:15 | 显示全部楼层
可以使用 wrapper 接口再次封装 自行实现
可参考 mebdos中的代码
mbed_alloc_wrappers.cpp

出15入178汤圆

发表于 2021-9-19 14:55:44 | 显示全部楼层
可以使用2分法快速判断出的内存剩余值,原理是逐次尝试malloc,成功后free

出0入362汤圆

发表于 2021-9-20 17:03:14 | 显示全部楼层
re楼上的
我写过

  1. static size_t __get_free_mem(size_t start, size_t end)
  2. {
  3.     unsigned char *p;
  4.     while (start < end - 1) {
  5.         size_t size = (start + end) / 2;
  6.         if (size == 0)
  7.             return 0;
  8.         p = malloc(size);
  9.         if (p != NULL) {        // malloc succeeded
  10.             free(p);
  11.             start = size;
  12.         } else {                // malloc failed
  13.             end = size - 1;
  14.         }
  15.     }
  16.     return start;
  17. }

  18. size_t get_free_mem(void)
  19. {
  20.     return __get_free_mem(0, 65536UL);
  21. }
复制代码

出0入0汤圆

 楼主| 发表于 2021-9-22 17:59:00 | 显示全部楼层
tomzbj 发表于 2021-9-20 17:03
re楼上的
我写过

这个思路不错哦,谢谢,收下了

出15入178汤圆

发表于 2021-9-22 23:44:58 | 显示全部楼层
tomzbj 发表于 2021-9-20 17:03
re楼上的
我写过

代码边界有问题,如输入参数0,2,FreeMemerySize=2时,返回1。

出15入178汤圆

发表于 2021-9-22 23:48:17 | 显示全部楼层
再例如参数start>=end时,返回start,代码并没有验证内存分配有没有成功

出0入0汤圆

 楼主| 发表于 2021-9-23 00:49:33 | 显示全部楼层
2nd 发表于 2021-9-22 23:44
代码边界有问题,如输入参数0,2,FreeMemerySize=2时,返回1。

最小数是1就可以了,
最大差1,这也无关紧要吧,实际应用都比较大,不会是2.
但有个问题,剩余空间是连续的才能检测正确吧。

出0入362汤圆

发表于 2021-9-23 09:06:47 | 显示全部楼层
2nd 发表于 2021-9-22 23:48
再例如参数start>=end时,返回start,代码并没有验证内存分配有没有成功

前面那个确实
后面这个不是问题, __get_free_mem函数不对外暴露, 只通过get_free_mem访问.

出0入362汤圆

发表于 2021-9-23 09:56:12 | 显示全部楼层
dog 发表于 2021-9-23 00:49
最小数是1就可以了,
最大差1,这也无关紧要吧,实际应用都比较大,不会是2.
但有个问题,剩余空间是连续 ...

不连续的话基本也只有最大空间有意义吧... 特别是在mcu上
一般都是尽可能避免使用malloc的

或者用bget之类第三方库?

出615入1076汤圆

发表于 2021-9-23 11:46:06 | 显示全部楼层
tomzbj 发表于 2021-9-23 09:56
不连续的话基本也只有最大空间有意义吧... 特别是在mcu上
一般都是尽可能避免使用malloc的

bget 說可以避免碎片,請問大概是什麼原理?

出0入362汤圆

发表于 2021-9-23 12:27:23 | 显示全部楼层
dukelec 发表于 2021-9-23 11:46
bget 說可以避免碎片,請問大概是什麼原理?

直接看源代码呗, 总共就1000多行

出0入0汤圆

 楼主| 发表于 2021-9-23 14:04:09 | 显示全部楼层
本帖最后由 dog 于 2021-9-23 16:04 编辑

按上面的思路,加了多次逼近,并用了三分法,
可以一定程度上,解决碎片,增加精度
大家看看有没有什么毛病没?



  1. unsigned long get_heap_free_space(void)
  2. {
  3.     const unsigned int TIMES = 12;  // 根据你的堆总尺寸,设置逼近的次数
  4.     const unsigned int HEAP_SIZE = 0x10000;  // 设置堆总尺寸
  5.     unsigned int free_space = 0;  // 用于剩余空间
  6.     unsigned int i;
  7.     unsigned char * p[TIMES] = {0}; // 用于分配的指针组
  8.     unsigned int size; // 当前分配的大小

  9.     size = HEAP_SIZE * 2 / 3; // 首次尝试总空间的2/3
  10.     for(i=0; i<TIMES; i++){
  11.         while(size){
  12.             p[i] = malloc(size);
  13.             if(p[i]){
  14.                 free_space += size;
  15.                 size = size * 2 / 3;   // 这里改了,缩小2/3, 执行速度会慢一点,但会一定程度上解决碎片问题。
  16.                 break;
  17.             }
  18.             size = size * 2 / 3;  // 失败后,再缩小为2/3
  19.         }
  20.     }

  21.     for(i=0; i<TIMES; i++){
  22.         if(p[i]){
  23.             free(p[i]);
  24.         }
  25.     }

  26.     return free_space;
  27. }

复制代码

出0入0汤圆

 楼主| 发表于 2021-9-23 14:36:24 | 显示全部楼层
下面是测试代码:


  1. void test_get_heap_free_space(unsigned long space)
  2. {
  3.     unsigned char * p;
  4.     unsigned long before;
  5.     unsigned long after;
  6.     long diff;
  7.     unsigned long tick;

  8.     DEBUG("test alloc space: %d", space);
  9.    
  10.     tick = TickGetUs();
  11.     before = get_heap_free_space();
  12.     tick = TickGetUs()-tick;
  13.     DEBUG("before: %d, time: %d us", before, tick);
  14.     p = malloc(space);
  15.     tick = TickGetUs();
  16.     after = get_heap_free_space();
  17.     tick = TickGetUs()-tick;
  18.     diff = before - after;
  19.     diff = diff - space;
  20.     DEBUG("after: %d, time: %d us", after, tick);
  21.     DEBUG("diff: %d", diff);
  22.     free(p);
  23.     DEBUG("\r\n");
  24. }
  25. int main(void)
  26. {
  27.     test_get_heap_free_space(1);
  28.     test_get_heap_free_space(2);
  29.     test_get_heap_free_space(3);
  30.     test_get_heap_free_space(4);
  31.     test_get_heap_free_space(100);
  32.     test_get_heap_free_space(1000);
  33.     test_get_heap_free_space(0x8000);
  34.     test_get_heap_free_space(0xE000);
  35. }

复制代码



  1. test alloc space: 1
  2. before: 59941, time: 20 us
  3. after: 59929, time: 20 us
  4. diff: 11


  5. test alloc space: 2
  6. before: 59941, time: 20 us
  7. after: 59929, time: 20 us
  8. diff: 10


  9. test alloc space: 3
  10. before: 59941, time: 20 us
  11. after: 59929, time: 20 us
  12. diff: 9


  13. test alloc space: 4
  14. before: 59941, time: 20 us
  15. after: 59929, time: 20 us
  16. diff: 8


  17. test alloc space: 100
  18. before: 59941, time: 21 us
  19. after: 59844, time: 20 us
  20. diff: -3


  21. test alloc space: 1000
  22. before: 59941, time: 21 us
  23. after: 58935, time: 19 us
  24. diff: 6


  25. test alloc space: 32768
  26. before: 59941, time: 21 us
  27. after: 27171, time: 21 us
  28. diff: 2


  29. test alloc space: 57344
  30. before: 59941, time: 21 us
  31. after: 2588, time: 21 us
  32. diff: 9


复制代码

出615入1076汤圆

发表于 2021-9-23 15:53:44 | 显示全部楼层
tomzbj 发表于 2021-9-23 12:27
直接看源代码呗, 总共就1000多行

看了下,沒看出來,依然會有碎片化的問題

出0入0汤圆

 楼主| 发表于 2021-9-23 16:02:15 | 显示全部楼层
dukelec 发表于 2021-9-23 15:53
看了下,沒看出來,依然會有碎片化的問題

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

本版积分规则

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

GMT+8, 2024-4-25 22:31

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

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