我们正在使用Micrium的uC / OS-III RTOS。 我们正在尝试在RTOS上返回malloc的值。 当我们在RTOS启动之前做一个99999的malloc(太多的RAM)时,我们得到一个空指针,这是我们所期望的。
当我们在启动RTOS和任务时执行相同的malloc时,我们不会返回空指针,这是我们不期望的。 尽管如此,系统确实会冻结。
有没有人对此有解释?
提前致谢
编辑:
有关信息:我们正在使用Renesas的RX62N微控制器和GNURX编译器
该程序实际上并未冻结。程序'认为'它获得一个有用的指针(不是NULL指针),并继续运行。在某一点上,程序将其程序计数器更改为00000000并停止。所以它没有进入异常,因此我们无法抓住它。
但是,在RTOS启动之前和启动RTOS时调用 malloc 会有所不同。区别在于 malloc 的真正深度汇编代码。
在某一点上执行以下指令
CMP R1,R7
BGTU.B 0FFF802C0H
ADD R14,R7
当我们尝试分配太多RAM时, BGTU.B 指令不应该分支,然后程序继续执行 ADD 指令。这在启动RTOS之前执行 malloc 时非常有效,而在之后执行时则失败。
These are the values I get in several cases
Outside RTOS (allocable number: 10)
R1: 00008348
R7: 00000014
Outside RTOS (not allocable number: 9999)
R1: 00008348
R7: 00002718
Inside RTOS (allocable number: 10)
R1: FFFFF9D0
R7: 00000014
Inside RTOS (not allocable number: 9999)
R1: FFFFF9D0
R7: 00002718
我希望整个情况都很明确,我试着尽可能地解释它:P
提前致谢
答案 0 :(得分:0)
除了插图案例中的第二种情况外,R7似乎包含分配的大小(请求的大小+对齐+堆管理数据)。直观地,R7 = 0x2718将对应于999字节的分配,因此我怀疑这可能是一个错字。
R1我猜想包含内存将被分配的堆块的大小,因为那样CMP就有意义了。如果块不够大,它将失败。
然而,当RTOS运行时,R1中的值变得非常大,显然不正确。如果您的堆损坏,可能会发生这种情况。如果超出堆上分配的缓冲区,则会发生这种情况。如果从堆中分配线程堆栈,并且堆栈太小,则会产生相同的效果。您的线程堆栈必须足够大,以适应最坏情况的调用堆栈,以及RTOS支持上下文切换所需的任何内容。即使您没有从堆中分配堆栈,如果线程堆栈与堆内存相邻,堆栈溢出也可能具有相同的效果。
堆可能被破坏的另一种方法是在多个线程中同时执行分配或释放,而不强制执行互斥或关键部分。标准库堆管理不太可能是线程安全的,除非您已经进行了必要的修改以将其与RTOS集成 - 如果RTOS和标准库来自同一供应商(例如,如果两者都提供的话)可能就是这种情况用编译器。)
答案 1 :(得分:0)
我们发现在UCOS-III操作系统启动之前调用malloc时工作正常。从线程调用时,它会失败并返回NULL指针。我怀疑这是由于对堆栈的检查,当在一个可以任意放置堆栈的线程中运行时当然无效。 我可以在地图文件中看到该库指的是特定的sbrk(lib_a-sbrk.o)函数,我无法找到该函数的任何来源。 众所周知,默认的GNU sbrk函数将检查当前堆栈指针,以查看当前中断是否超出SP并失败。
不幸的是我们必须依赖malloc,因为我们使用复杂的C ++库,因为我们有几兆字节的内存而不关心碎片,我们只想让malloc工作。我们实际上甚至不关心重入,因为我们只在单个线程中使用malloc。
是否有可能阐明如何在库中实现堆函数。我们正在使用ARM-9芯片。