"main"函数堆栈中的对象在第一个任务运行时被覆盖 (FreeRTOS)

Object in stack of `main` function is overwritten when first task runs (FreeRTOS)

本文关键字:quot 运行时 覆盖 FreeRTOS 任务 对象 函数 main 堆栈 第一个      更新时间:2023-10-16

我尝试用一个简单的例子来解释我的问题

typedef function<bool()> TaskCallback;
class Task
{
public:
Task(TaskCallback task_callback) : task_callback(task_callback)
{
long_string_test = "This is a long string 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF";
xTaskCreate(Task::RunTask, "task_name", 2560, this, 3, &task_handle);
}
~Task()
{
while(1); //Breakpoint: The destructor is never called
}
private:
static void RunTask(void* params)
{
Task* _this = static_cast<Task*>(params);
_this->task_callback(); //The program crashes here because task_callback doesn't exist
}
string long_string_test;
TaskCallback task_callback;
TaskHandle_t task_handle;
};

主.cpp

static bool Init_task() { }
void main()
{
Task task(Init_task);
vTaskStartScheduler();
//We should never get here as control is now taken by the FreeRTOS scheduler
while(1);
}

如果我通过RunTask函数中的 debbugerlong_string_test检查字符串的值,我发现它有一个奇怪的值,就好像字符串已被销毁一样。 但是Task类的析构函数从未被召唤过。

如果我更改"main.cpp",如下所示,程序可以正常工作,我认为编译器会进行某种优化:

static bool Init_task() { }
Task task(Init_task);
void main()
{
vTaskStartScheduler();
//We should never get here as control is now taken by the FreeRTOS scheduler
while(1);
}

附言显然编译器优化被禁用

作为vTaskStartScheduler调用的一部分,prvPortStartFirstTask将重置堆栈指针。我可以想象,这最终会导致其他代码覆盖分配给main的废弃堆栈空间上的部分Task对象。您可以使用调试器设置数据断点,但我认为第一个任务开始时main堆栈空间被丢弃。

我认为这里最好的解决方案确实是静态分配Task对象,或者可能使用堆分配(如果您的系统允许的话(。

@Botje 你是对的,我改变了我的例子来验证你所说的。

主.cpp

int* test;
static void RunTask(void* params)
{
Print(*test);  //The "test" pointer has a random value
}
void main()
{
int temp = 9999;
test = &temp;
xTaskCreate(RunTask, "task_name", 2560, NULL, 3, NULL);
vTaskStartScheduler(); //It seems that FreeRTOS clears the main() stack
//We should never get here as control is now taken by the FreeRTOS scheduler
while(1);
}