In principe this worked just fine, up to the addition of a queue and some class members. When I look at ‘this’ inside the constructor xTaskCreate, this looks fine.
At the end, when call_logger is called, the void pointer points to the same address as this. But, after casting, no class members are set correctly. It seems they all point to zero’s.
I’m not seeing all your code, so the problem might be elsewhere. One big thought that comes to mind is that you can’t create the object as a local object in main, as many of the ports use the main functions stack to be the ISR stack after the scheduler starts, so variable there get broken.
A second thing to watch out for, but doesn’t seem to be the problem here, is conversion to and back from a void pointer. If you convert a derived class pointer directly to a void pointer, and then back to the base class, you might not get the right pointer, you need to first convert the derived class pointer to the base class pointer, and then to a void pointer.
The strangest part of this code is, it works perfectly well on an ESP32 using IDF.
But it is going wrong (like stated in my first message) using an STM32G4 and the STM32 IDE.
(I cannot find the data breakpoints in STM32 IDE…)
When I create the queue inside the Logger class, that pointer still exists after casting. The m_Handle is still lost, which is strange because it is instantiated in the constructor of the class using the xCreateTask method.
I tested your Logger on a Zynq-700, but it didn’t show mentioned problem.
Now you are casting from Logger * to void * and vv.
I came up with this idea:
class Logger;
struct this_holder
{
Logger *this_cpy;
};
class Logger {
public:
this_holder holder;
Logger(xQueueHandle queue);
virtual ~Logger();
...
};
Logger::holder is a simple struct , holding a copy of the this pointer.
So in stead of passing a pointer this a Logger object, you pass a pointer to its Logger::holder.
Would that make a difference?
Or would it make a difference if Logger has no virtual members?
EDIT : I forgot to attach the complete code as I tested it. Here is is:
Removing the virtual methods in the class, does not solve the issue.
Using the ‘this_holder’ shifts the problem. The pointer to the ‘this_holder’ seems to make sense. But, looking at the pointer (this_cpy) to ‘this’ is pointing to NULL.
Maybe the STM32G4 in combination with FreeRTOS handles the stack differently compared to my ESP32 or your Zynq-700?!
The logger object is allocated on main stack, which is reset by FreeRTOS when starting the scheduler for some MCUs like Cortex-M3/4/7 for exclusive use by ISRs. The object might or will get corrupted. There are already a number of related posts in the forum.
Try allocating it on heap (new) or make it (module) static or global and add e.g. a set-ter method for the queue handle.
To the people who didn’t get it immediately: the stack that is used in the function main() might be recycled: it will (often) be used as a stack for ISR’s, interrupt handlers.
In @ErX example, the Logger object on the stack got corrupted as soon as the first interrupts occurs.
Lesson to learn: within main() is OK to declare objects on the stack. But do no try to access them after the schedulers has been started, because the “main stack” will be re-used for other purposes.