我正在为STM32F7编写一个嵌入式软件,我的libc是newlib-2.4.0.20160527。newlib中的malloc():一次大的故障分配后会浪费内存吗?
我已经实现_sbrk()
如下:
extern intptr_t g_bss_end; /* value after the last byte in .bss */
extern intptr_t g_msp_lim; /* stack buffer starts at this address */
intptr_t _sbrk(ptrdiff_t heap_incr)
{
static intptr_t heap_end = 0;
intptr_t prev_heap_end;
intptr_t new_heap_end;
if(heap_end == 0) {
heap_end = (intptr_t)&g_bss_end;
}
prev_heap_end = heap_end;
new_heap_end = prev_heap_end + heap_incr;
if(new_heap_end >= g_msp_lim) {
errno = ENOMEM;
return -1;
}
heap_end = new_heap_end;
return prev_heap_end;
}
然后,当我做到以下几点:
/* total capacity of my heap is 0x40000 */
void * mem = malloc(0x40000);
free(mem); mem = 0;
mem = malloc(0x40000);
一切正常(即malloc的返回非零的两倍)。
但是,当我这样做(用于测试目的):
for(int32_t sz = 0x50000; sz >= 0; sz--) {
void * mem = malloc(sz);
if(mem != 0) {
__BKPT();
free(mem);
break;
}
}
每malloc()
失败,甚至malloc(0)
(即__BKPT()
是从未达到)。所以,实际上并没有在堆上分配内存(我没有得到任何mem != 0
,所以我什至不能free()
东西),也没有可用的内存。
我预计malloc()
失败,每sz > 0x40000
并为每sz <= 0x40000
(假设每个free()
后malloc()
正常工作)取得成功。
我错过了什么,或者这是bug或在newlib中的预期行为?
调试器说什么?你是否已经完成了代码?注意:在嵌入式系统中使用基于堆的动态内存分配像'malloc'通常是一个坏主意,许多编码标准出于正当理由不允许使用这种分配。值得注意的是确定性行为和保证分配。在甚至考虑'malloc'等之前,先评估池或其他度量方法(如静态变量)的使用! – Olaf
哦,并用指针的'NULL'宏。 '0'作为空指针常量是有效的,但是C++程序员的坏习惯。出于好的理由,C++ 11引入了'nullptr'。 (希望C11跟着他们) – Olaf
我通过我的代码(我检查了'mem'的值;'__BKPT()'也是一个断点)。为了使用gdb进入newlib的代码,我现在用'-g3 -O0'重新编译它。我想要工作'snprintf',它依赖'malloc'。我应该开始搜索'snprintf'选项吗?我不需要'malloc'来做其他事情。 –