【发布时间】:2017-01-20 23:11:20
【问题描述】:
2016-12 年更新 现在还有一个关于这种行为的最小示例:https://community.nxp.com/message/862676
我正在使用带有 freertos 的 ARM Cortex M4,使用 freescales Freedom Kinetis IDE(gnu arm 工具链)。问题是
try {
throw 4; // old scenario also not working: throw std::runtime_error("wut");
} catch (...) {
}
导致 CPU 停止,try 之后的代码或(当添加一些时)catch 处理程序中的代码未执行。
可以在这里找到组装:https://gist.github.com/Superlokkus/3c4201893b4c51e154e2a0afdf78fef0
我假设这会导致 SVC 中断,很抱歉我弄错了,Freertos 欺骗了我,因为当我抛出一些东西时它会在 DefaultISR 中停止。
throw 确实跳转到 __cxa_throw 然后从那里跳转到 ___Unwind_RaiseException __gnu_Unwind_RaiseException __cxa_begin_catch>
<_zst9terminatev>
所以看起来 std::terminate 被调用了,但是 catch all 块不应该允许这样做。或者我的假设是错误的,这种行为是因为 gcc C++ 运行时异常支持是一个总是调用终止的存根?!
2016-09 更新:因为我看到 rand() 尝试使用 malloc(),所以我还定义了一个有效的 malloc()/freeRTOS 函数,等等:__cxa_allocate_exception 使用 malloc(我想知道工具链希望我如何处理 bad_alloc 案例)。 所以现在,它仍然崩溃,但是在异常分配之后(我认为): 执行路径为:
(throwing function after exception allocation)
__cxa_throw
... //(some intructions in __cxa_throw)
__cxa_begin_catch //I guess something went wrong here
_ZSt9terminatev // Immediately after __cxa_begin_catch
_ZN10__cxxabiv111__terminateEPFvvE:
00016dfc: push {r3, lr}
00016dfe: blx r0 //Goes directly to WDOG_EWM_IRQHandler or hard fault handler
00016e00: bl 0x194ac <abort>
如果您想知道或者它可能会有所帮助:如果我没有定义 hard_fault 处理程序和自己的默认处理程序,我的调试器会说它是我崩溃的 WDOG_EWM_IRQHandler。
所以我猜堆栈展开时出了点问题,因为我在 _throw 中通过了一些名称中带有“完成的堆栈展开”的符号,但我没有捕捉到我在对象的析构函数中设置的断点应该已经清理干净了。这似乎促使 __cxa_begin_catch 调用 abort 之类的。
( Kinetis Design Studio 3.2.0. 与 GNU ARM C/C++ 交叉编译器 版本:1.12.1.201502281154 对于我们的 FRDM-KV31F)
【问题讨论】:
-
恕我直言,对于嵌入式设备,c++ 异常机制有点复杂。 FreeRTOS 也使用 SVC 中断,所以如果你这样做,你必须知道你做了什么来避免破坏 FreeRTOS
-
你说的是C++异常还是ARM内核异常?
-
我不知道 gcc 期望从那里调用什么,但是您必须在 FreeRTOS 上方插入自己的
SVC_Handler以检查它为什么到达那里。SVC接受一个以R0IIRC 结尾的参数,而 FreeRTOS 默认调用SVC #0,因此根据 gcc 为SVC参数插入的内容,您可能能够区分来源。不过,它会阻止您担心的 RTOS 中断。 -
我所能看到的只是 IAR EWARM 是如何处理它的,它在不使用处理器异常的情况下处理它。你能发布一个 MCVE 的反汇编吗?
-
您是否设置了看门狗并对其进行了适当的维护?我也遇到了放入错误向量的问题,因此如果您放入的向量没有意义,请仔细检查您的向量表上的对齐方式是否正确。
标签: c++ arm embedded freertos cortex-m