使用newlib nano malloc时sbrk的增量值从何而来?
Where does the increment value for sbrk come from when using newlib nano malloc?
我有一个目标 (Stm32f030R8),我正在使用 FreeRTOS 和 newlib 可重入堆实现 (http://www.nadler.com/embedded/newlibAndFreeRTOS.html)。除了实现实际的 FreeRTOS 内存分配 shim 之外,此 shim 还定义了 sbrk。该项目是使用 GNU ARM GCC 构建的,并使用 --specs=nosys.specs.
下面的例子,FreeRTOS还没有启动。之前没有调用过 malloc。 MCU 刚刚启动,刚刚将初始化数据从闪存复制到 RAM 中,并配置了时钟和基本外围设备。
只是在我的项目中拥有 lib,我看到 sbrk 被调用时使用了非常大的增量值来进行看似很小的 malloc 调用。
目标有8K内存,其中我有0x12b8(堆开始和ram结束(堆栈顶部)之间~4KB字节)。
我发现如果我使用 str = (char*) malloc(1000);
分配 1000 个字节,sbrk 会被调用两次。首先使用增量值 0x07e8,然后再次使用增量值 0x0c60。结果是所需的总增量计数为 0x1448(5192 字节!)当然这不仅溢出了堆栈,还溢出了可用的 ram。
这到底是怎么回事?为什么 malloc 使用这些巨大的增量值来分配相对较小的所需缓冲区?
我认为可能无法确定地回答,而不仅仅是建议调试。最简单的解决方案是逐步执行分配代码以确定分配大小请求在何处以及为何被破坏(看起来如此)。您将需要从源代码构建库,或者至少在您的代码中包含 mallocr.c 以覆盖任何静态库实现。
在 Newlib Nano 中,_sbrk_r
的调用堆栈相当简单(与常规 Newlib 相比)。增量由nano-mallocr.c中nano_malloc()
中的分配大小s
决定如下:
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
的块(当 free()
没有被调用时总是这种情况),那么 sbrk_aligned( alloc_size )
被调用调用 _sbrk_r()
。 None 的填充、对齐或最小分配宏添加了这么大的量。
如果请求未对齐,sbrk_aligned( alloc_size )
调用 _sbrk_r
。第二次调用不应大于 CHUNK_ALIGN
- (sizeof(void*)
).
在您的调试器中,您应该能够检查调用堆栈或单步执行调用以查看参数在哪里不正确。
我有一个目标 (Stm32f030R8),我正在使用 FreeRTOS 和 newlib 可重入堆实现 (http://www.nadler.com/embedded/newlibAndFreeRTOS.html)。除了实现实际的 FreeRTOS 内存分配 shim 之外,此 shim 还定义了 sbrk。该项目是使用 GNU ARM GCC 构建的,并使用 --specs=nosys.specs.
下面的例子,FreeRTOS还没有启动。之前没有调用过 malloc。 MCU 刚刚启动,刚刚将初始化数据从闪存复制到 RAM 中,并配置了时钟和基本外围设备。
只是在我的项目中拥有 lib,我看到 sbrk 被调用时使用了非常大的增量值来进行看似很小的 malloc 调用。
目标有8K内存,其中我有0x12b8(堆开始和ram结束(堆栈顶部)之间~4KB字节)。
我发现如果我使用 str = (char*) malloc(1000);
分配 1000 个字节,sbrk 会被调用两次。首先使用增量值 0x07e8,然后再次使用增量值 0x0c60。结果是所需的总增量计数为 0x1448(5192 字节!)当然这不仅溢出了堆栈,还溢出了可用的 ram。
这到底是怎么回事?为什么 malloc 使用这些巨大的增量值来分配相对较小的所需缓冲区?
我认为可能无法确定地回答,而不仅仅是建议调试。最简单的解决方案是逐步执行分配代码以确定分配大小请求在何处以及为何被破坏(看起来如此)。您将需要从源代码构建库,或者至少在您的代码中包含 mallocr.c 以覆盖任何静态库实现。
在 Newlib Nano 中,_sbrk_r
的调用堆栈相当简单(与常规 Newlib 相比)。增量由nano-mallocr.c中nano_malloc()
中的分配大小s
决定如下:
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
的块(当 free()
没有被调用时总是这种情况),那么 sbrk_aligned( alloc_size )
被调用调用 _sbrk_r()
。 None 的填充、对齐或最小分配宏添加了这么大的量。
sbrk_aligned( alloc_size )
调用 _sbrk_r
。第二次调用不应大于 CHUNK_ALIGN
- (sizeof(void*)
).
在您的调试器中,您应该能够检查调用堆栈或单步执行调用以查看参数在哪里不正确。