Using Embedded Memory Explorer to Track Code Dependencies
In this tutorial we will show how to use the Embedded Memory Explorer to track dependencies between various parts of your program. We will create a basic multi-threaded application based on FreeRTOS and will attempt using the STL types in it and show what problem it triggers and how to solve it.
Before you begin, install VisualGDB 5.2 or later.
- Start Visual Studio and open the VisualGDB Embedded Project Wizard:
- Select “Create a new project -> Embedded Binary” and click “next”:
- On the next page select your toolchain and the device. We will use the STM32F4Discovery board with STM32F407VG, but the steps described below will work with any other board that can run FreeRTOS:
- On the Sample Selection page choose the FreeRTOS sample:
- Finally select your debug method on the Debug Method page:
- Press “Finish” to generate the project. Then change the main file source extension from .c to .cpp and add extern “C” to the declaration of SysTick_Handler:
extern "C" void SysTick_Handler(void) { osSystickHandler(); }
- Now we will modify the code to use the vector and string classes from STL:
#include <vector> #include <string> static void LED_Thread1(void const *argument) { for (;;) { std::vector<std::string> vec; vec.push_back("test1"); vec.push_back("test2"); vec.push_back("test3"); } } static void LED_Thread2(void const *argument) { for (;;) { std::vector<std::string> vec; vec.push_back("test1"); vec.push_back("test2"); vec.push_back("test3"); } }
- Press F5 to build and run the project. It will quickly trigger an exception in the operator new():
- Most memory-related problems under FreeRTOS are caused by accidental use of the standard malloc() and free() functions that are not aware of the FreeRTOS scheduler. So when a thread switch happens while malloc() or free() is running, this ultimately leads to memory corruption. Open the Embedded Memory Explorer via the View menu and locate the malloc() or _malloc_r() function:
- Click the ‘show dependencies’ button in the toolbar. VisualGDB will suggest enabling relocation record generation for the project. Click “yes” and build the project again:
- Now you can enable the dependency view in memory explorer. Expand the dependencies for _malloc_r() to see the list of functions using it:The dependency view quickly shows that malloc() is used by the C++ operator new() that is in turn used by the vector and string allocators.
- The easiest way to fix this is to provide custom new() and delete() operators that will use the thread-aware FreeRTOS heap functions:
void * operator new(size_t size) { return pvPortMalloc(size); } void operator delete(void *p) { vPortFree(p); }
- Build the project. The memory explorer will show that the _malloc_r() function is only used by __sfmoreglue() that is in turn only used by the libc initialization code:
- As there are no more references to malloc() and free() from the code that runs in FreeRTOS threads, it should no longer cause a crash. Press F5 to launch the project and confirm that the crash never happens. If you stop the project now, you should see that both threads are running normally: