Continue to use static task stack after owning task has been deleted

Say I have a task which uses preallocated memory. This memory will never be occupied by any other object during the program duration. Can I then assume that all references and pointers to objects within that buffer resolve correctly even after the underlying task has been deleted?

Compare the following: Here I create a task which resides on statically allocated memory. It spawns another (dynamically allocated) task that receives a reference to a stack local variable of the static task. Can it continue to use it without restrictions (assuming that the buffer is not again occupied by another statically allocated task…)?

#include <stdio.h>

#include <iostream>

#include "freertos/FreeRTOS.h"

#include "freertos/queue.h"

#include "freertos/task.h"

#include <array>

#include <memory>

StackType_t stack_buffer[1024];

StaticTask_t task_buffer;

void some_other_task(void* param)

{

    int& a = *static_cast<int*>(param);

    std::cout << "before: " << a << std::endl;

    vTaskDelay(100);

    a = 3;

    std::cout << "after: " << a << std::endl;

    vTaskDelay(portMAX_DELAY);

}

void some_task(void* param)

{

    int a = 5;

    xTaskCreate(some_other_task, "other task", 1024, &a, 10, NULL);

    vTaskDelete( NULL );

}

extern "C" void app_main(void)

{

    // TaskHandle_t xHandle;

    xTaskCreateStatic(some_task, "task", 1024, NULL, 10, stack_buffer, &task_buffer);

    vTaskDelay(portMAX_DELAY);

}

Technically, you have invoked undefined behavior, as you are accessing a variable after its lifetime has ended. Practically, it should work.

Note, since you have extern “C”, that means you must be compiling as C++, which means that objects in the first task would have had their destructors run if they were in a scope smaller than the vTaskDelete, and those are much more problematic, as they will continue as destroyed objects which are generally unsafe to access (you can normally get away with it if the destructor is ‘trivial’)