本文介绍了嵌入式系统上的malloc行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在从事一个嵌入式项目(STM32F103RB,带有arm-none-eabi-gcc 4.8 2013q4的CooCox CoIDE v.1.7.6),并且我试图了解malloc()在普通C上的表现当RAM已满时.

I'm currently working on an embedded project (STM32F103RB, CooCox CoIDE v.1.7.6 with arm-none-eabi-gcc 4.8 2013q4) and I'm trying to understand how malloc() behaves on plain C when the RAM is full.

我的STM32具有20kB = 0x5000Bytes的RAM,0x200用于堆栈.

My STM32 has 20kB = 0x5000Bytes of RAM, 0x200 are used for the stack.

#include <stdlib.h>
#include "stm32f10x.h"

struct list_el {
   char weight[1024];
};

typedef struct list_el item;

int main(void)
{
    item * curr;

    // allocate until RAM is full
    do {
        curr = (item *)malloc(sizeof(item));
    } while (curr != NULL);

    // I know, free() is missing. Program is supposed to crash

    return 0;
}

我希望malloc()会在堆太小而无法分配时返回NULL:

I would expect malloc() to return NULL as soon as the heap is too small for allocating:

0x5000(RAM)-0x83C(bss)-0x200(堆栈)= 0x45C4(堆)

0x5000 (RAM) - 0x83C (bss) - 0x200 (stack) = 0x45C4 (heap)

因此,当第18次执行malloc()时.一项为1024 = 0x400字节大.

So when executing the malloc() for the 18th time. One item is 1024=0x400 Bytes large.

但是,uC会在第18次之后调用HardFault_Handler(void)(甚至不是MemManager_Handler(void))

But instead the uC calls the HardFault_Handler(void) after the 18th time (not even the MemManager_Handler(void))

有人建议如何预测malloc()失败-因为等待NULL返回似乎无效.

Does anybody have an advice how to forecast a malloc() failure - since waiting for a NULL return doesn't seem to work.

谢谢.

推荐答案

malloc似乎根本没有做任何检查.您遇到的错误来自硬件检测到对无效地址的写入,这很可能来自malloc本身.

It does not look like malloc is doing any checks at all. The fault that you get comes from hardware detecting a write to an invalid address, which is probably coming from malloc itself.

malloc分配内存时,它将从其内部池中获取一个块,并将其返回给您.但是,它需要存储一些信息,以便free函数能够完成释放.通常,这就是块的实际长度.为了保存该信息,malloc从块本身的开头开始占用了几个字节,在其中写入了信息,并向您返回了写入其自己的信息的地址之后的地址.

When malloc allocates memory, it takes a chunk from its internal pool, and returns it to you. However, it needs to store some information for the free function to be able to complete deallocation. Usually, that's the actual length of the chunk. In order to save that information, malloc takes a few bytes from the beginning of the chunk itself, writes the info there, and returns you the address past the spot where it has written its own information.

例如,假设您要一个10字节的块. malloc将获取一个可用的16字节块,例如在地址0x3200..0x320F处,将长度(即16)写到字节1和2中,然后将0x3202返回给您.现在,您的程序可以使用从0x32020x320B的十个字节.其他四个字节也可用-如果您呼叫realloc并要求14个字节,则不会进行重新分配.

For example, let's say you asked for a 10-byte chunk. malloc would grab an available 16-byte chunk, say, at addresses 0x3200..0x320F, write the length (i.e. 16) into bytes 1 and 2, and return 0x3202 back to you. Now your program can use ten bytes from 0x3202 to 0x320B. The other four bytes are available, too - if you call realloc and ask for 14 bytes, there would be no reallocation.

关键点是当malloc将长度写入将要返回给您的内存块中时:它写入的地址必须有效.看起来,在第18次迭代之后,下一个块的地址为负(这转化为非常大的正数),因此CPU捕获了写操作并触发了硬故障.

The crucial point comes when malloc writes the length into the chunk of memory that it is about to return to you: the address to which it writes needs to be valid. It appears that after the 18-th iteration the address of the next chunk is negative (which translates to a very large positive) so CPU traps the write, and triggers the hard fault.

在堆和堆栈彼此靠近的情况下,没有可靠的方法来检测内存不足,同时又让您使用内存的最后一个字节,这通常是非常需要的. malloc无法预测分配后要使用多少堆栈,因此它甚至不会尝试.这就是为什么大多数情况下字节计数在您身上的原因.

In situations when the heap and the stack grow toward each other there is no reliable way to detect an out of memory while letting you use every last byte of memory, which is often a very desirable thing. malloc cannot predict how much stack you are going to use after the allocation, so it does not even try. That is why the byte counting in most cases is on you.

通常,在空间限制为几十千字节的嵌入式硬件上,可以避免在任意"位置进行malloc调用.相反,您可以使用一些预先计算的限制来预先分配所有内存,然后将其打包到需要它的结构中,而不再调用malloc.

In general, on embedded hardware when the space is limited to a few dozen kilobytes, you avoid malloc calls in "arbitrary" places. Instead, you pre-allocate all your memory upfront using some pre-calculated limits, and parcel it out to structures that need it, and never call malloc again.

这篇关于嵌入式系统上的malloc行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-22 19:20
查看更多