首页 > 解决方案 > 使用newlib nano malloc时sbrk的增量值从何而来?

问题描述

我有一个目标(Stm32f030R8),我正在使用 FreeRTOS 和 newlib 可重入堆实现(http://www.nadler.com/embedded/newlibAndFreeRTOS.html)。除了实现实际的 FreeRTOS 内存分配 shim 之外,此 shim 还定义了 sbrk。该项目使用 GNU ARM GCC 并使用 --specs=nosys.specs 构建。

对于以下示例,尚未启动 FreeRTOS。malloc 之前没有被调用过。MCU 刚刚启动,刚刚将初始化数据从闪存复制到 ram 和配置的时钟和基本外围设备。

只需在我的项目中使用该库,我就看到 sbrk 被调用,对于看似很小的 malloc 调用来说,增量值非常大。

目标有 8K 的内存,其中我有 0x12b8(在堆的开始和 ram 的结束(堆栈的顶部)之间有大约 4KB 字节。

我看到,如果我用 分配 1000 个字节str = (char*) malloc(1000);,则 sbrk 会被调用两次。首先是增量值为 0x07e8,然后是增量值为 0x0c60。结果是所需的总增量计数为 0x1448(5192 字节!),当然这不仅会溢出堆栈,还会溢出可用的 ram。

这到底是怎么回事?为什么 malloc 将这些巨大的增量值用于如此相对较小的所需缓冲区分配?

标签: memoryembeddedstm32headnewlib

解决方案


我认为可能无法明确回答,而不仅仅是建议调试。最简单的解决方案是逐步检查分配代码以确定分配大小请求被破坏的位置和原因(看起来是这样)。您将需要从源代码构建库,或者至少在代码中包含 mallocr.c 以覆盖任何静态库实现。

在 Newlib Nano 中,调用堆栈_sbrk_r相当简单(与常规 Newlib 相比)。s增量由 nano-mallocr.c中的分配大小确定nano_malloc(),如下所示:

malloc_size_t alloc_size;
alloc_size = ALIGN_TO(s, CHUNK_ALIGN); /* size of aligned data load */
alloc_size += MALLOC_PADDING; /* padding */
alloc_size += CHUNK_OFFSET; /* size of chunk head */
alloc_size = MAX(alloc_size, MALLOC_MINCHUNK);

alloc_size然后,如果在空闲列表中找不到一块 of (在free()没有被调用的情况下总是如此),则sbrk_aligned( alloc_size )调用调用 _ sbrk_r()。填充、对齐或最小分配宏都没有添加这么大的数量。

sbrk_aligned( alloc_size )_sbrk_r如果请求未对齐,则调用。第二次调用不应大于CHUNK_ALIGN- ( sizeof(void*))。

在您的调试器中,您应该能够检查调用堆栈或单步执行调用以查看参数在哪里变得不正确。


推荐阅读