【发布时间】:2017-02-01 05:10:23
【问题描述】:
我有一个使用 gcc-arm-none-eabi toolchanin 编译的准系统 arm 控制器。 我注意到向 malloc() 请求 132 个字节,这反过来导致 malloc() 调用 sbrk() 两次,首先请求大小 152 B,然后在返回之前请求 4100 B。
Malloc() 在这种情况下是从 sprintf() 调用的,似乎每个格式化程序 (%d, %f, ...) 都分配了自己的内存。重复使用一个标识符不会导致更多的分配。使用 %f 时分配 4100 B。
在这种情况下,4 kB 不是问题。但我想知道它不会要求另一个类似的金额。
malloc 应该分配这么多吗?
我可以设置什么来阻止它吗?
我是否应该担心 malloc 可能会要求更多空间(无缘无故)?
sbrk 代码不是工具链提供的代码。 malloc 被包装了,所以我可以看到会发生什么。
char *_cur_brk;
void *_sbrk_r(struct _reent *reent, ptrdiff_t diff)
{
void *_old_brk = _cur_brk;
monitor_printf("_sbrk_r called with size = %d. cur_brk = %p \t", diff, _cur_brk);
void * ptr;
ptr = __builtin_return_address(0);
monitor_printf("Called from %d: %p\t", 0, ptr );
monitor_printEOL();
extdiff = diff;
if ( (_cur_brk + diff ) > _HeapLimit ) {
sbrk_error += 1;
errno = ENOMEM;
monitor_printf(" failed, cur_brk=%d, HeapLimit=%d", _cur_brk, _HeapLimit);
monitor_printEOL();
return (void *)-1;
}
sbrk_error = 0;
_cur_brk += diff;
monitor_printf("return %p", _old_brk);
monitor_printEOL();
return _old_brk;
}
void * __wrap__malloc_r( struct _reent *reent, size_t size )
{
void * ret;
monitor_printf("wrap_malloc_r called with size = %d.", size);
monitor_printEOL();
ret = __real__malloc_r( reent, size );
return ret;
}
调用 malloc(132) 的输出
wrap_malloc_r called with size = 132.
_sbrk_r called with size = 152. cur_brk = 0x20005f64 Called from 0: 0x801311b
return 0x20005f64
_sbrk_r called with size = 4100. cur_brk = 0x20005ffc Called from 0: 0x8013181
return 0x20005ffc
Memory allocated at 0x20005f70lling malloc(132)
谢谢 /约翰
【问题讨论】:
-
为什么你会在裸机微控制器上使用 malloc?这没有任何意义——ARM 不是 PC。 Read this.
-
@Lundin:如今的微控制器可以拥有比最初的 IBM PC 更多的内存。您提供的链接指的是一个微控制器,
malloc确实没有意义,但您不能只是假设在这里加入也是如此。 -
@joing:这是一致的,还是仅在第一次通话时?
malloc可能会在第一次调用时设置一个 4kB 的簿记页面 -
@MSalters 内存量并不是它没有意义的原因。缺乏多进程桌面操作系统是。
-
@MSalters 不使用基于堆的动态内存分配的另一个原因是碎片。一个打算运行数月甚至数年的系统必须具有可预测的内存行为。
标签: c gcc embedded malloc heap-memory