`main` 函数堆栈中的对象在第一个任务运行时被覆盖 (FreeRTOS)
Object in stack of `main` function is overwritten when first task runs (FreeRTOS)
我试着用一个简单的例子来解释我的问题
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;
};
main.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
函数中的调试器检查字符串 long_string_test
的值,我发现它有一个奇怪的值,就好像该字符串已被破坏。
但是 Task
class 的析构函数从未被调用过。
如果我按如下所示更改 "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);
}
p.s。显然编译器优化被禁用
作为 vTaskStartScheduler
调用的一部分,prvPortStartFirstTask
将 reset the stack pointer。我可以想象,这最终会导致其他代码覆盖分配给 main
的废弃堆栈 space 上的 Task
对象的部分内容。您可以使用调试器设置数据断点,但我会认为 main
堆栈 space 在第一个任务开始时被丢弃。
我认为这里最好的解决方案确实是静态分配 Task
对象或可能使用堆分配(如果您的系统允许的话)。
@Botje 你是对的我改变了我的例子来验证你说的。
main.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);
}
我试着用一个简单的例子来解释我的问题
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;
};
main.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
函数中的调试器检查字符串 long_string_test
的值,我发现它有一个奇怪的值,就好像该字符串已被破坏。
但是 Task
class 的析构函数从未被调用过。
如果我按如下所示更改 "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);
}
p.s。显然编译器优化被禁用
作为 vTaskStartScheduler
调用的一部分,prvPortStartFirstTask
将 reset the stack pointer。我可以想象,这最终会导致其他代码覆盖分配给 main
的废弃堆栈 space 上的 Task
对象的部分内容。您可以使用调试器设置数据断点,但我会认为 main
堆栈 space 在第一个任务开始时被丢弃。
我认为这里最好的解决方案确实是静态分配 Task
对象或可能使用堆分配(如果您的系统允许的话)。
@Botje 你是对的我改变了我的例子来验证你说的。
main.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);
}