2

我们使用的是 Micrium 的 uC/OS-III RTOS。我们正在尝试在 RTOS 上返回 malloc 的值。当我们在 RTOS 启动之前执行 99999 的 malloc(对于 RAM 来说太多)时,我们会得到一个空指针,这正是我们所期望的。

当我们在 RTOS 启动和任务中执行相同的 malloc 时,我们不会得到空指针,这是我们不期望的。不过,系统此时确实冻结了。

有人对此有解释吗?

提前致谢

编辑:

信息:我们使用的是瑞萨电子的 RX62N 微控制器和 GNURX 编译器

该程序实际上并没有冻结。程序“认为”它得到了一个有用的指针(不是 NULL 指针),并继续运行。在某个时刻,程序将其程序计数器更改为 00000000 并停止。所以它不会进入异常,因此我们无法捕获它。

但是,在 RTOS 启动之前调用 malloc 和在 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

提前致谢

4

2 回答 2

0

除了示例中的第二种情况,R7 似乎包含分配的大小(请求的大小 + 对齐 + 堆管理数据)。直观地说,R7=0x2718 对应于 999 字节的分配,所以我怀疑这可能是一个错字。

我猜 R1 包含将分配内存的堆块的大小,因为那时 CMP 才有意义。如果块不够大,它将失败。

但是当 RTOS 运行时,R1 中的值变得非常大,显然是不正确的。如果您的堆损坏,则可能会发生这种情况。如果您超出堆上分配的缓冲区,就会发生这种情况。如果您从堆中分配线程堆栈,并且堆栈太小,那将具有相同的效果。您的线程堆栈必须足够大,以应对最坏情况的调用堆栈,以及 RTOS 支持上下文切换所需的任何内容。即使您没有从堆中分配堆栈,如果线程堆栈与堆内存相邻,堆栈溢出也可能产生相同的效果。

堆损坏的另一种方法是在多个线程中同时执行分配或解除分配,而不强制互斥或临界区。标准库堆管理不太可能是线程安全的,除非您进行了必要的修改以将其与您的 RTOS 集成 - 如果 RTOS 和标准库来自同一供应商(例如,如果两者都提供),则可能是这种情况与编译器)。

于 2012-05-21T16:16:53.210 回答
0

我们发现在 UCOS-III 操作系统启动之前调用 malloc 可以正常工作。当从线程调用时,它会失败并返回一个 NULL 指针。我怀疑这是由于对堆栈的检查,当在可以具有任意放置堆栈的线程中运行时,这当然是无效的。我可以在映射文件中看到该库引用了特定的 sbrk (lib_a-sbrk.o) 函数,但我找不到该函数的任何来源。众所周知,默认的 GNU sbrk 函数会检查当前堆栈指针以查看当前中断是否超出 SP 并失败。

不幸的是,我们必须依赖 malloc,因为我们使用的是复杂的 C++ 库,因为我们有兆字节的内存,我们不关心碎片,我们只希望 malloc 工作。实际上,我们甚至不关心重入,因为我们只在单个线程中使用 malloc。

是否有可能阐明堆函数是如何在库中实现的。我们使用的是 ARM-9 芯片。

于 2016-08-29T19:25:05.070 回答