首页 > 解决方案 > malloc() 如何在穿孔堆中分配内存?

问题描述

我正在处理微控制器上 malloc () 和 calloc () 的分配。我能够直接读出我的 HEAP / STACK 所在的 SRAM,而我无法直接向自己解释的一件事让我印象深刻。

基本上在我的项目中,内存被分配了几次。所以我通过 malloc() 将我的内存“划分”为各个分配的内存区域,从地址 0x24000000 开始到 0x2407D000 之类的东西。我可以在内存中看到这一点,并使用分配的内存区域上的指针。

简单地说,这些区域看起来像:

/******************************************/
//                Region 1                //
//        0x24000000 to 0x24000540        //
//                                        //
/******************************************/
//                Region 2                //
//        0x24000548 to 0x24001598        //
//                                        //
/******************************************/
//                Region 3                //
//        0x240015A0 to 0x24076A10        //
//                                        //
/******************************************/

顺序如下:第一个分配是region 1的原因,第二个是region 2的原因,第三个是region 3(比较大的内存)的原因。之后 Region 2 被 free() 清空。

现在分配了两个小内存,它们很容易放入前一个区域 2。我希望第一个小内存分配的地址为 0x24000550,第二个内存在之后的某个地方。但是,似乎内存是按相反的顺序分配的,因为第一个分配的小内存的地址为 0x24001590,而第二个分配的小内存的地址为 0x24001570。所以我的问题是“malloc () 如何处理这个分配?我认为内存是从堆中的最低地址分配到最高地址的?”

我希望你能听懂我的英语,我还是觉得有点难。无论如何,非常感谢您的回答!

标签: cmemorymemory-management

解决方案


I am assuming you are using newlib standard C library implementation in it's nano verison.

How does malloc () handle this allocation?

Region2 is added to the free_list. Then when in malloc() the free_list is iterated, and we find a region greater then alloc_size, where alloc_size is the requested size with added space for metadata and padding for alignment.

r = free_list;
while(r) {
    int rem = r->size - alloc_size;
    if (rem >= 0) // we have enough size
    {
        if (rem >= MALLOC_MINCHUNK)
        {
            /* Find a chunk that much larger than required size, break
            * it into two chunks and return the second one */
            r->size = rem;
            r = (chunk *)((char *)r + rem);
            r->size = alloc_size;
        }
   .....

r points to the current element in the free_list. The if (rem >= MALLOC_MINCHUNK) is true, then we decrease the size of the current element in the free list by alloc_size at r->size = rem; (because rem = r->size - alloc_size; - rem is the remaining memory if we had made the allocation). Then r = (chunk *)((char *)r + rem); becomes the allocated memory chunk in the list that has r->size = alloc_size; the allocated size. Note that the returned chunk is offset by rem - so it's on the end. So indeed the regions in the free_list are split "from the back".

I thought memory is allocated from the lowest address to the highest in the heap?

There is no rule and nothing can be assumed. Every implementation is different.


推荐阅读