Hello,
For unit testing purposes, I have incorreprated some active objects to be within the Catch2 framework. Because of how Catch2 works, this leads to said objects being created/deleted within the same execuatable. This works just fine with active objects alone, however, problems arise once an active QTimeEvt is deleted. This is as when an active QTimeEvt is deleted is it still linked in the global linked list timeEvtHead and thus becomes a dangling pointer.
To get around this I have created a custom qp.hpp and qf_time.cpp which includes a custom destructor which removes it from the linked list. The diff to v7.3.1 is as follows
qp.hpp
> ~QTimeEvt();
qf_time.cpp
> QTimeEvt::~QTimeEvt()
> {
> std::uint8_t const tickRate = refCtr_ & TE_TICK_RATE;
> QTimeEvt *prev = &timeEvtHead_[tickRate];
> QF_CRIT_STAT
> QF_CRIT_ENTRY();
> // scan the linked-list of time events at this rate...
> for (;;) {
> QTimeEvt *t = prev->m_next; // advance down the time evt. list
>
> // end of the list?
> if (t == nullptr)
> {
> if (timeEvtHead_[tickRate].m_act != nullptr)
> {
> // sanity check
> Q_ASSERT_INCRIT(110, prev != nullptr);
> prev->m_next = timeEvtHead_[tickRate].toTimeEvt();
> timeEvtHead_[tickRate].m_act = nullptr;
> t = prev->m_next; // switch to the new list
> }
> else
> {
> break; // all currently armed time evts. processed
> }
> }
>
> // time event scheduled for removal?
> if (t == this) {
> prev->m_next = t->m_next;
> // mark time event 't' as NOT linked
> t->refCtr_ = static_cast<std::uint8_t>(t->refCtr_
> & static_cast<std::uint8_t>(~TE_IS_LINKED));
> }
> else
> {
> prev = t;
> }
> }
> QF_CRIT_EXIT();
> }
Having this or any varyition which preserves this behavoir to the library would be greatly benifical.
Regards
Anonymous
The destructor declarations for various QP classes have been added in the latest QP/C++ 7.3.1. But all these declarations are disabled by default and require providing the macro
Q_XTOR. The reason is that the presence of (virtual) destructors pulls in thedeleteoperator from the library. This in turn, pulls infree()as well asmalloc()and other functions highly undesirable in most high reliability embedded software.Please note that only some of these destructors are actually defined in QP/C++, so if the destructors are enabled (by defining the macro
Q_XTOR), the destructors for the following classes must be provided in the application (of course, you might use the destructor you proposed for~QTimeEvt()):Finally, I would caution against tests that rely on cleanup from the previous tests, especially in C++ because the constructors of static objects don't run. Alarming number of tests pass only because of inadvertent side effects of preceeding tests. This provides a false sense of security and is highly counterproductive. The only truly reliable tests are those that immediately follow a clean system reset. This is precisely how QUTest unit testing harness is designed.
--MMS
Last edit: Quantum Leaps 2023-12-07