Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
memheap
rt_malloc
RT-Thread一般讨论
10
memheap内存分配释放问题
发布于 2025-04-21 18:24:44 浏览:136
订阅该版
[tocm] ## 配置描述: 硬件平台STM32F767IIT6,FMC挂载了2块SRAM,8位数据宽度,共用数据线和地址线,使用NE3和NE4片选切换,对应起始地址分别为:0x68000000和0x6C000000,IDE:RT-Thread Studio,系统版本:4.1.1,使用memheap作为内存堆,已经启用RT_USING_MEMHEAP_AS_HEAP ## 问题描述 使用rt_malloc分配的内存大小和预期不符,使用rt_free释放后内存大小没有恢复反而变的更少了 ## 链接文件如下 ```c /* * linker script for STM32F767II with GNU ld */ /* Program Entry, set to mark it as "used" and avoid gc */ MEMORY { ROM (rx) : ORIGIN =0x08020000,LENGTH =1920k RAM (rw) : ORIGIN =0x20020000,LENGTH =384k EX_SRAM1 (rw) : ORIGIN =0x68000000,LENGTH =1024k EX_SRAM2 (rw) : ORIGIN =0x6C000000,LENGTH =1024k } ENTRY(Reset_Handler) _system_stack_size = 0x400; SECTIONS { .text : { . = ALIGN(4); _stext = .; KEEP(*(.isr_vector)) /* Startup code */ . = ALIGN(4); *(.text) /* remaining code */ *(.text.*) /* remaining code */ *(.rodata) /* read-only data (constants) */ *(.rodata*) *(.glue_7) *(.glue_7t) *(.gnu.linkonce.t*) /* section information for finsh shell */ . = ALIGN(4); __fsymtab_start = .; KEEP(*(FSymTab)) __fsymtab_end = .; . = ALIGN(4); __vsymtab_start = .; KEEP(*(VSymTab)) __vsymtab_end = .; /* section information for utest */ . = ALIGN(4); __rt_utest_tc_tab_start = .; KEEP(*(UtestTcTab)) __rt_utest_tc_tab_end = .; /* section information for at server */ . = ALIGN(4); __rtatcmdtab_start = .; KEEP(*(RtAtCmdTab)) __rtatcmdtab_end = .; . = ALIGN(4); /* section information for initial. */ . = ALIGN(4); __rt_init_start = .; KEEP(*(SORT(.rti_fn*))) __rt_init_end = .; . = ALIGN(4); PROVIDE(__ctors_start__ = .); KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) PROVIDE(__ctors_end__ = .); . = ALIGN(4); _etext = .; } > ROM = 0 /* .ARM.exidx is sorted, so has to go in its own output section. */ __exidx_start = .; .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) /* This is used by the startup in order to initialize the .data secion */ _sidata = .; } > ROM __exidx_end = .; /* .data section which is used for initialized data */ .data : AT (_sidata) { . = ALIGN(4); /* This is used by the startup in order to initialize the .data secion */ _sdata = . ; *(.data) *(.data.*) *(.gnu.linkonce.d*) PROVIDE(__dtors_start__ = .); KEEP(*(SORT(.dtors.*))) KEEP(*(.dtors)) PROVIDE(__dtors_end__ = .); . = ALIGN(4); /* This is used by the startup in order to initialize the .data secion */ _edata = . ; } >RAM .stack : { . = ALIGN(4); _sstack = .; . = . + _system_stack_size; . = ALIGN(4); _estack = .; } >RAM __bss_start = .; .bss : { . = ALIGN(4); /* This is used by the startup in order to initialize the .bss secion */ _sbss = .; *(.bss) *(.bss.*) *(COMMON) . = ALIGN(4); /* This is used by the startup in order to initialize the .bss secion */ _ebss = . ; *(.bss.init) } > RAM __bss_end = .; /* sram section */ /* 动态内存堆 */ .sram (NOLOAD): { . = ALIGN(4); _ssram = .; *(.sram) *(.sram.*) . = ALIGN(4); _esram = .; } > EX_SRAM1 /* sram2 section */ .sram2_data : { . = ALIGN(4); _ssram2_data = .; *(.sram2.data) . = ALIGN(4); _esram2_data = .; } > ROM .sram2_bss (NOLOAD): { . = ALIGN(4); _ssram2_bss = .; *(.sram2.bss) . = ALIGN(4); _esram2_bss = .; } > EX_SRAM2 .sram2 : { . = ALIGN(4); _ssram2 = .; *(.sram2) . = ALIGN(4); _esram2 = .; } > EX_SRAM2 _end = .; /* Stabs debugging sections. */ .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } .stab.excl 0 : { *(.stab.excl) } .stab.exclstr 0 : { *(.stab.exclstr) } .stab.index 0 : { *(.stab.index) } .stab.indexstr 0 : { *(.stab.indexstr) } .comment 0 : { *(.comment) } /* DWARF debug sections. * Symbols in the DWARF debugging sections are relative to the beginning * of the section so we begin them at 0. */ /* DWARF 1 */ .debug 0 : { *(.debug) } .line 0 : { *(.line) } /* GNU DWARF 1 extensions */ .debug_srcinfo 0 : { *(.debug_srcinfo) } .debug_sfnames 0 : { *(.debug_sfnames) } /* DWARF 1.1 and DWARF 2 */ .debug_aranges 0 : { *(.debug_aranges) } .debug_pubnames 0 : { *(.debug_pubnames) } /* DWARF 2 */ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } .debug_abbrev 0 : { *(.debug_abbrev) } .debug_line 0 : { *(.debug_line) } .debug_frame 0 : { *(.debug_frame) } .debug_str 0 : { *(.debug_str) } .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { *(.debug_macinfo) } /* SGI/MIPS DWARF 2 extensions */ .debug_weaknames 0 : { *(.debug_weaknames) } .debug_funcnames 0 : { *(.debug_funcnames) } .debug_typenames 0 : { *(.debug_typenames) } .debug_varnames 0 : { *(.debug_varnames) } } ``` ## 启动文件如下,省去最后部分中断描述 ```c /** ****************************************************************************** * @file startup_stm32f767xx.s * @author MCD Application Team * @brief STM32F767xx Devices vector table for GCC based toolchain. * This module performs: * - Set the initial SP * - Set the initial PC == Reset_Handler, * - Set the vector table entries with the exceptions ISR address * - Branches to main in the C library (which eventually * calls main()). * After Reset the Cortex-M7 processor is in Thread mode, * priority is Privileged, and the Stack is set to Main. ****************************************************************************** * @attention * * Copyright (c) 2016 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ .syntax unified .cpu cortex-m7 .fpu softvfp .thumb .global g_pfnVectors .global Default_Handler /* start address for the initialization values of the .data section. defined in linker script */ .word _sidata /* start address for the .data section. defined in linker script */ .word _sdata /* end address for the .data section. defined in linker script */ .word _edata /* start address for the .bss section. defined in linker script */ .word _sbss /* end address for the .bss section. defined in linker script */ .word _ebss /* sram2 data start and end addresses */ .word _ssram2_data .word _esram2_data /* sram2 bss start and end addresses */ .word _ssram2_bss .word _esram2_bss /* sram2 start and end addresses */ .word _ssram2 .word _esram2 /* stack used for SystemInit_ExtMemCtl; always internal RAM used */ /** * @brief This is the code that gets called when the processor first * starts execution following a reset event. Only the absolutely * necessary set is performed, after which the application * supplied main() routine is called. * @param None * @retval : None */ .section .text.Reset_Handler .weak Reset_Handler .type Reset_Handler, %function Reset_Handler: ldr sp, =_estack /* set stack pointer */ /* Copy the data segment initializers from flash to SRAM */ ldr r0, =_sdata ldr r1, =_edata ldr r2, =_sidata movs r3, #0 b LoopCopyDataInit CopyDataInit: ldr r4, [r2, r3] str r4, [r0, r3] adds r3, r3, #4 LoopCopyDataInit: adds r4, r0, r3 cmp r4, r1 bcc CopyDataInit /* Zero fill the bss segment. */ ldr r2, =_sbss ldr r4, =_ebss movs r3, #0 b LoopFillZerobss FillZerobss: str r3, [r2] adds r2, r2, #4 LoopFillZerobss: cmp r2, r4 bcc FillZerobss /* Configure FMC Controller */ /* bl DRV_SRAM_Init */ /* Initialize SRAM2 Data */ /* ldr r0, =_ssram2 ldr r1, =_esram2 ldr r2, =_ssram2_data ldr r3, =_esram2_data bl rt_copy_to_sram2 */ /* ldr r0, =_ssram2 ldr r1, =_esram2_data ldr r2, =_ssram2_data bl rt_copy_to_sram2 */ /* Zero fill the SRAM2 BSS segment. */ ldr r2, =_ssram2_bss ldr r4, =_esram2_bss movs r3, #0 b LoopFillZerobssSRAM2 FillZerobssSRAM2: str r3, [r2] adds r2, r2, #4 LoopFillZerobssSRAM2: cmp r2, r4 bcc FillZerobssSRAM2 /* Call the clock system initialization function.*/ bl SystemInit /* Call static constructors */ bl __libc_init_array /* Call the application's entry point.*/ bl entry bx lr .size Reset_Handler, .-Reset_Handler /** * @brief This is the code that gets called when the processor receives an * unexpected interrupt. This simply enters an infinite loop, preserving * the system state for examination by a debugger. * @param None * @retval None */ .section .text.Default_Handler,"ax",%progbits Default_Handler: Infinite_Loop: b Infinite_Loop .size Default_Handler, .-Default_Handler /****************************************************************************** * * The minimal vector table for a Cortex M7. Note that the proper constructs * must be placed on this to ensure that it ends up at physical address * 0x0000.0000. * *******************************************************************************/ .section .isr_vector,"a",%progbits .type g_pfnVectors, %object .size g_pfnVectors, .-g_pfnVectors g_pfnVectors: .word _estack .word Reset_Handler .word NMI_Handler .word HardFault_Handler .word MemManage_Handler .word BusFault_Handler .word UsageFault_Handler .word 0 .word 0 .word 0 .word 0 .word SVC_Handler .word DebugMon_Handler .word 0 .word PendSV_Handler .word SysTick_Handler /* External Interrupts */ .word WWDG_IRQHandler /* Window WatchDog */ .word PVD_IRQHandler /* PVD through EXTI Line detection */ .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ .word FLASH_IRQHandler /* FLASH */ .word RCC_IRQHandler /* RCC */ ``` ## memheap初始化代码 ```c /* USER CODE BEGIN 0 */ #define RAM_HEAP_EX_START (0x68000000) #define RAM_HEAP_EX_SIZE (1024 * 1024) #define RAM_HEAP_EX_END (RAM_EX_START + RAM_EX_SIZE) struct rt_memheap ex_ram_heap; int DRV_EX_SRAM_Register(void) { rt_memheap_init(&ex_ram_heap,"SRAM EX",(void*)RAM_HEAP_EX_START,RAM_HEAP_EX_SIZE); return 0; } INIT_COMPONENT_EXPORT(DRV_EX_SRAM_Register); ``` ## 关键测试代码 ```c static char *G_pDataBuf; static void cmd_debug(int argc, char *argv[]) { rt_int32_t cnt = 0; if (argc < 2) { debug_test_usage(); return ; } if(argc>=3){ cnt = atoi(argv[2]); log_printf("cnt:%d",cnt); if (0 == rt_strcmp("malloc", argv[1])) { G_pDataBuf = rt_malloc(cnt*4); if(G_pDataBuf!=RT_NULL){ log_printf("Allocated %d bytes memory.",cnt*4); } } else if (0 == rt_strcmp("calloc", argv[1])) { G_pDataBuf = rt_calloc(1,cnt*4); if(G_pDataBuf!=RT_NULL){ log_printf("Allocated %d bytes memory.",cnt*4); } } } else if(argc==2){ if (0 == rt_strcmp("free", argv[1])) { rt_free(G_pDataBuf); log_printf("free done"); } } else { debug_test_usage(); return; } } MSH_CMD_EXPORT(cmd_debug, cmd debug); ``` ## 日志如下 内存分配前内存情况如下所示 ```c pool size max used size available size -------- ---------- ------------- -------------- SRAM EX 1048576 48 1048528 heap 221988 151924 71780 msh /> ``` 使用rt_malloc分配4字节的内存后内存情况如下所示,可以看到实际分配了400字节 ```c msh />cmd_debug malloc 1 1.[1970-01-01 08:01:40.688][debug_thread.c 986]:cnt:1 2.[1970-01-01 08:01:40.693][debug_thread.c 991]:Allocated 4 bytes memory. msh />free pool size max used size available size -------- ---------- ------------- -------------- SRAM EX 1048576 48 1048528 heap 221988 151924 71380 msh /> ``` 使用rt_free释放后,内存情况如下所示 ```c msh />cmd_debug free 3.[1970-01-01 08:02:53.608][debug_thread.c 1006]:free done msh />free pool size max used size available size -------- ---------- ------------- -------------- SRAM EX 1048576 48 1048528 heap 221988 151924 71292 msh /> ``` 可以看到分配的内存和实际不符,且执行释放后内存没有恢复反而变的更少了,不知为何,请各位大佬帮忙看看是什么原因,感谢。
查看更多
3
个回答
默认排序
按发布时间排序
张世争
2025-04-22
学以致用
`malloc(cnt*128);` 这里为何需要乘上 128,并且打印信息 `Allocated 4 bytes memory.` 4 又是怎么出来的?代码不一致?
踩姑娘的小蘑菇
2025-04-22
这家伙很懒,什么也没写!
~~评论里这个逻辑有点问题,`cmd_debug free`这条指令的argc为2 `if(argc>=3)`的判断应该改为>=2~~ 看错了,不是这里的问题 配置memtrace跟踪下看看吧
rv666
认证专家
2025-04-22
用GDB调试人生
1.首先在这个分配内存的前后调用free函数看一下内存  2.使用小内存管理的话打开内存调试memtrace
撰写答案
登录
注册新账号
关注者
0
被浏览
136
关于作者
xingchen8910
这家伙很懒,什么也没写!
提问
4
回答
14
被采纳
0
关注TA
发私信
相关问题
1
BSD的一些代码分析
2
RT-Thread文件系统
3
怎么文档,源码还是没有呀??
4
[ZT]嵌入式LwIP协议栈的内存管理
5
RTLinux/RTCore体系结构
6
RTLinux/RTCore局限性
7
怎样获取源码
8
[ZT]The lightest lightweight threads, Protothreads
9
[ZT]微内核操作系统及L4概述
10
关于操作系统对C++操作符的使用
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
基于RT-Thread的STM32F4开发第三讲——DAC
2
Wireshark抓包EtherCAT报文
3
RISC-V hardfault分析工具,RTTHREAD-RVBACKTRACE 原理讲解
4
基于RT-Thread的STM32G4开发第二讲第二篇——ADC
5
基于RT-Thread的STM32F4开发第二讲第一篇——ADC
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
DMA
USB
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
FAL
RTC
rt-smart
I2C_IIC
cubemx
UART
ESP8266
WIZnet_W5500
BSP
ota在线升级
PWM
flash
packages_软件包
freemodbus
潘多拉开发板_Pandora
ADC
GD32
定时器
编译报错
flashDB
keil_MDK
socket
中断
rt_mq_消息队列_msg_queue
Debug
ulog
SFUD
msh
C++_cpp
at_device
本月问答贡献
出出啊
1524
个答案
343
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
818
个答案
179
次被采纳
crystal266
555
个答案
162
次被采纳
whj467467222
1222
个答案
149
次被采纳
本月文章贡献
出出啊
1
篇文章
1
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
2
次点赞
crystal266
2
篇文章
1
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部