【发布时间】:2023-04-06 04:45:01
【问题描述】:
我正在为 STM32F7 编写一个嵌入式软件,我的 libc 是 newlib-2.4.0.20160527。
我已经实现_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() 之后都能正常工作)。
我是否遗漏了什么,或者这是 newlib 中的错误或预期行为?
【问题讨论】:
-
调试器说什么?您是否单步执行了代码?注意:在嵌入式系统中使用像
malloc这样的基于堆的动态内存分配通常是一个坏主意,许多编码标准出于充分的理由不允许这样做。尤其是确定性行为和保证分配。在考虑malloc等之前评估池或其他措施(如静态变量)的使用! -
哦,使用带有指针的
NULL宏。0作为空指针常量是有效的,但是 C++ 程序员的一个坏习惯。 C++11 引入nullptr是有充分理由的。 (希望 C11 跟着他们) -
我单步执行了我的代码(我检查了
mem的值;__BKPT()也是一个断点)。为了用 gdb 进入 newlib 的代码,我现在用-g3 -O0重新编译它。我想要工作snprintf,它依赖于malloc。我应该开始搜索snprintf替代品吗?我不需要malloc做其他任何事情。 -
也许您应该首先了解嵌入式软件开发。流 IO 函数也是主要的资源消耗者。虽然我想知道为什么
snprintf会需要malloc。 -
@Olaf
0是 C 中的空指针常量。这不是“C++ 的坏习惯”,早在 C++ 发明之前就一直使用它
标签: c embedded malloc newlib sbrk