Dynamic Memory Allocation
Let's try to compile simple application that uses dynamic memory allocation. The test_cpp_vector application contains the following code:
It may happen that linking operation will fail with multiple referenced symbols being undefined:
The symbols __exidx_start
and __exidx_end
are required to indicate start and end of .ARM.exidx
section. It is used for exception handling. They must be defined in the linker script:
The dynamic memory allocation will require implementation of _sbrk
function which will be used to allocate chunks of memory for the C/C++ heap management.
All other symbols will be required to properly support exceptions which are used by C++ heap management system. Here is a good resource, that lists all the system calls, the developer may need to implement, to get the application compiled.
Now, after successful compilation, take a good look at the size of the images of two sample applications we compiled. The paths are <build_dir>/src/test_cpp/test_cpp_simple/kernel.img
and <build_dir>/src/test_cpp/test_cpp_vector/kernel.img
.
Side note: The image can be generated out of elf binary using the following instruction:
arm-none-eabi-objcopy -O binary
You may notice that size of test_cpp_vector image is greater by approximately 100K than test_cpp_simple. It is due to C++ heap management and exceptions handling. Let's try to see what happens to the size of the application if "C++" heap is replaced with “C” one without exceptions. You will have to override all the global C++ operators responsible for memory allocation/deallocation:
Please compile the test_cpp_vector application again, create its image and take a look at its size. It will be much closer to the size of the test_cpp_simple image. In fact, you may not even need majority of the system call functions you have implemented before. Try to remove them one by one and see whether linker still reports “undefined reference” to these symbols.
CONCLUSION: Usage of C++ heap brings a significant code size overhead. It is a good practice to override implementation of new
and delete
operators with usage of malloc
and free
when using C++ in bare metal development. Note that in this case, if memory allocation fails nullptr will be returned instead of throwing std::bad_alloc exception, so beware of third party C++ libraries that count on exception been thrown and do not check the returned value form operator new.
Excluding Usage of Dynamic Memory
The dynamic memory allocation is a core part of conventional C++. However, in some bare-metal products the usage of dynamic memory may be problematic and/or forbidden. The only way (I know of) to make to compilation fail, if dynamic memory is used, is to exclude standard library altogether. With gcc
compiler it is achieved by using -nostdlib
compilation option.
Excluding standard library from the compilation will remove the whole C++ run-time environment, which includes dynamic memory (heap) management and exception handling. The implication of using this compilation option will be described later in Removing Standard Library and C++ Runtime section.
Last updated