首页 > 系统相关 >如何确保不使用动态内存

如何确保不使用动态内存

时间:2022-12-25 10:04:55浏览次数:56  
标签:脚本 sbrk startup 如何 确保 动态内存 使用 链接

  在许多嵌入式应用程序中,内存分配必须是静态的,而不是动态的。意味着在应用程序中不应使用对malloc()或free()等内容的调用,因为它们可能会在运行时失败(内存不足、堆碎片)。

如何确保不使用动态内存_内存分配

  但是,当与第三方库甚至 C/C++ 标准库链接时,如何确保不使用动态内存?对于C++对象或对 printf()的简单调用,也可能会出现此问题,该调用需要在内部分配一些动态内存。

1、零堆大小?

  一种简单(而且相当幼稚)的方法是将堆大小设置为零。大多数链接器脚本或链接器环境都能够将堆大小设置为零,如下所示:

如何确保不使用动态内存_FreeMarker_02

  但是,这无济于事,因为大多数链接器脚本只使用堆栈空间和变量 (bss) 之间的可用空间: 因此,将堆大小设置为零只是假设保留为零,但库的 _sbrk()将继续使用动态内存,可能会崩溃到堆栈空间。

如何确保不使用动态内存_FreeMarker_03

  底线:大多数链接器脚本堆大小设置为零将无济于事。它甚至增加了堆崩溃到堆栈中的可能性,因为链接器假定堆的使用量为零。但它不会阻止使用堆。

2、堆在链接器文件中

  这可以从下面显示的链接器文件中看出:

如何确保不使用动态内存_FreeMarker_04

  若要确保不使用堆,最简单的方法是简单地删除上述链接器文件中的 .heap 分配。检查链接器文件中是否有“堆”或类似内容,并确保没有为其分配内存。特别是确保没有使用符号“__prvHeapStart”或“__prvHeapLimit”,因为它们通常是newlib/newlib-nano库动态内存分配所必需的。

3、链接器自由标记脚本

  恩智浦MCUXpresso IDE等某些环境正在使用自动生成的链接器文件。但是,如果您了解它使用的FreeMarker脚本,则很容易处理此问题。脚本位于

<MCUXpresso IDE Installation Path>\ide\Wizards\linker

  所以我可以使用修改后的 FreeMarker 脚本轻松禁用 .heap:

如何确保不使用动态内存_FreeMarker_05

4、__sbrk()

  删除堆及其符号后,malloc()的任何用法都应该给出一个链接器错误,类似于这个错误:

Invoking: MCU Linker
arm-none-eabi-gcc -nostdlib -Xlinker -Map="AEMBS_tinyK22_HS22.map" -Xlinker --gc-sections -Xlinker -print-memory-usage -Xlinker --sort-section=alignment -Xlinker --cref -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -T "AEMBS_tinyK22_HS22_Debug.ld" -o "AEMBS_tinyK22_HS22.axf" ./utilities/fsl_assert.o ... ./McuLib/FreeRTOS/FreeRTOShooks.o
arm-none-eabi/bin/ld.exe: arm-none-eabi/lib/thumb/v7e-m+fp/hard\libcr_newlib_semihost.a(_cr_sbrk.o): in function `_sbrk':
_cr_sbrk.c:(.text._sbrk+0x38): undefined reference to `_pvHeapStart'

5、链接器交叉引用

  如果不清楚使用内存分配或导致错误的原因,可以使用链接器交叉引用。为此,必须将 GNU 链接器 –cref 选项添加到链接器选项中:

如何确保不使用动态内存_内存分配_06

  这会在链接器 .map 文件中生成如下所示的信息:

Cross Reference Table

Symbol File
ADC0_DriverIRQHandler ./startup/startup_mk22f51212.o
ADC0_IRQHandler ./startup/startup_mk22f51212.o
ADC16_ClearStatusFlags ./drivers/fsl_adc16.o
ADC16_Deinit ./drivers/fsl_adc16.o
...
main ./source/main.o
./startup/startup_mk22f51212.o
malloc arm-none-eabi/lib/thumb/v7e-m+fp/hard\libc_nano.a(lib_a-malloc.o)
arm-none-eabi/lib/thumb/v7e-m+fp/hard\libc_nano.a(lib_a-rand.o)
./drivers/fsl_common.o
mcgConfig_BOARD_BootClockRUN ./board/clock_config.o

  这给出了使用 malloc()之类的模块列表。

6、图像信息

  找出依赖关系的另一种方法是在 Eclipse/MCUXpresso 中使用“图像信息”视图,请参阅在构建后操作中列出具有 GNU 大小实用程序的所有文件的代码和数据大小:

如何确保不使用动态内存_动态内存_07

7、免费实时操作系统静态内存分配

  更多旁注:默认情况下,FreeRTOS 使用自己的动态堆分配。但是可以静态方式运行 RTOS(无动态内存分配),请参阅带静态内存分配的 FreeRTOS V9.0.0。

8、总结

  许多应用程序不需要动态内存分配和使用。为了防止使用 malloc()和 free(),最好删除链接器文件中的任何堆定义,以导致链接器错误。那么 GNU 链接器交叉引用表或图像信息可能非常有用。

9、链接

  • 使用 FreeMarker 脚本的示例:教程:将 BLE+NRF Kinetis Design Studio Project 移植到 MCUXpresso IDE
  • 带有 FreeMarker 脚本的引导加载程序:将引导加载程序应用程序与 Eclipse 和 FreeMarker 脚本链接起来
  • 自由标记脚本:​​https://freemarker.apache.org/​

欢迎关注:

如何确保不使用动态内存_内存分配_08

如果阅读这篇文章让您略有所得,还请点击下方的按钮。

当然,如果您想及时了解我的博客更新,不妨点击下方的按钮。

如果您希望更方便且及时的阅读相关文章,也可以扫描上方二维码关注我的微信公众号【木南创智



标签:脚本,sbrk,startup,如何,确保,动态内存,使用,链接
From: https://blog.51cto.com/u_520887/5967867

相关文章