Memory 使用newlib nano malloc时,sbrk的增量值来自哪里?

Memory 使用newlib nano malloc时,sbrk的增量值来自哪里?,memory,embedded,stm32,head,newlib,Memory,Embedded,Stm32,Head,Newlib,我有一个目标(Stm32f030R8)用于FreeRTOS和newlib可重入堆实现()。除了实现实际的FreeRTOS内存分配垫片外,该垫片还定义了sbrk。该项目是使用GNU ARM GCC和--specs=nosys.specs构建的 对于以下示例,FreeRTOS尚未启动。以前从未调用过malloc。mcu刚从启动状态恢复,只将初始化数据从闪存复制到ram中,并配置时钟和基本外围设备 只要在我的项目中有lib,我就可以看到sbrk被调用,对于看似很小的malloc调用,它的增量值非常大

我有一个目标(Stm32f030R8)用于FreeRTOS和newlib可重入堆实现()。除了实现实际的FreeRTOS内存分配垫片外,该垫片还定义了sbrk。该项目是使用GNU ARM GCC和--specs=nosys.specs构建的

对于以下示例,FreeRTOS尚未启动。以前从未调用过malloc。mcu刚从启动状态恢复,只将初始化数据从闪存复制到ram中,并配置时钟和基本外围设备

只要在我的项目中有lib,我就可以看到sbrk被调用,对于看似很小的malloc调用,它的增量值非常大

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

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


这里到底发生了什么?为什么malloc会使用这些巨大的增量值来进行相对较小的期望缓冲区分配?

我认为不可能给出明确的答案,而只是建议进行调试。最简单的解决方案是逐步通过分配代码来确定分配的位置和原因ze请求已损坏(看起来是这样)。您需要从源代码构建库,或者至少在代码中包含mallocr.c以覆盖任何静态库实现

在Newlib Nano中,对
\u sbrk\u r
的调用堆栈相当简单(与常规Newlib相比)。增量由Nano mallocr.c中
Nano\u 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\u size
块(未调用
free()
时总是这样),则调用
sbrk\u aligned(alloc\u size)
,调用<
sbrk\u r()
。填充、对齐或最小分配宏都不会添加这么多

sbrk\u aligned(alloc\u size)
如果请求未对齐,则调用
\u sbrk\u r
。第二次调用不得大于
CHUNK\u ALIGN
-(
sizeof(void*)


在调试器中,您应该能够检查调用堆栈或单步执行调用,以查看参数错误的位置。

您是否检查了堆是否已正确初始化?通常在跳到
main
之前由C运行时完成。IIRC在函数
\ulibc\u init\u array
中完成取决于所使用的CRT。它甚至可能不会初始化堆,因为在Cortex M0上使用堆没有任何意义。@Lundin你是什么意思?你是说在没有堆的情况下使用malloc吗?@GuillaumePetitjean我的意思是CRT甚至可能不会初始化堆/堆。因为在为Cortex M0编码时,你不应该想要或需要堆。除非你的程序效率太高或是其他原因,我想…@chris12892不,你不明白,这是每个定义的开销,没有任何好处。你也可以静态分配内存,不同的是没有开销代码,也没有访问静态内存的分段。而你分配的内存或者,不管您是否使用堆,都会分配堆,那么您得到了什么?您的程序在任何情况下都必须分配足够的内存以覆盖最坏的使用情况。您不能“保存”内存就像在PC中一样,因为除了你的程序之外,没有其他人可以使用内存。我不可能回答这个问题,如果没有完整的项目。我也不相信OPs调试技能(因此我不知道显示的值是否有意义),因为否则第一步(也是最琐碎的一步)是查看调用sbrk的内容,然后调试调用方。@0\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,那么这将是一个答案。我同意调用者可能是问题所在,答案是一样的-使用调试器。我并不是说Newlib Nano代码就是错误所在;但是观察增量是如何确定的是发现原因的一种方法。这最终是我问题的答案。我只是问这些值在哪里我没有要求任何人调试我的项目,否则我会在咨询合同中公布整个项目:)。问题很简单,“这就是我所看到的,增值从哪里来?”。谢谢@chris12892正如您所看到的,我通过检查代码确定了这一点。事实上,我从未使用过Newlib Nano。关键是它是开源的,没有什么是对你隐藏的。