Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bare metal without global operator new

Consider safety software, where dynamic allocation in general is disallowed and exceptions are disallowed. Dynamic allocation is allowed only when class explicity defines operator new and delete. Using operator new for others class should cause compilation failure.

The simplest way to cause compilation failure in described situation is to remove global new operator:

void* operator new(std::size_t) = delete;

On the one hand this cause side effects with standard library. For example including <array> propagates inclusion to <new_allocator> by <stdexcept>. <new_allocator> uses ::new operator and this cause build fail even when You don't want to use exception and memory allocation. According to Scoot Meyers <array> should be bare metal friendly.

On the other hand this cause error with compiler built-in operator

src/main.cpp:91:31: error: deleted definition of 'void* operator new(std::size_t)'
 void* operator new(std::size_t) = delete;                               ^
<built-in>: note: previous declaration of 'void* operator new(std::size_t)'

Is there any solution to ban ::new and use <array>?

Is there any solution to ban ::new globally at all?

like image 339
JD. Avatar asked Jan 02 '17 11:01

JD.


People also ask

What is bare-metal C++?

Bare-metal programming is a term for programming that operates without various layers of abstraction or, as some experts describe it, "without an operating system supporting it." Bare-metal programming interacts with a system at the hardware level, taking into account the specific build of the hardware.

How does malloc work on bare-metal?

In a bare-metal environment, it's usually best not to use malloc at all. Instead, use memory pools that manage a fixed number of fixed-size memory blocks. In a bare-metal environment, malloc often doesn't exist. If it does exist, then check the documentation for wherever it came from.

What is bare-metal programming?

Bare-metal programming is generally understood to mean that an application is written directly on the hardware without using an external programming interface, i.e. an operating system. Applications access here directly hardware registers of microcontrollers.


3 Answers

If you use GCC and GNU LD, then I think you can just add --wrap=malloc to your linker flags. As global ::new uses malloc() internally, all calls to malloc() in your application will be replaced with __wrap_malloc(). If this function is undefined, then the linking will fail.

Another, possibly simpler option, is to add ASSERT(DEFINED(malloc) == 0, "Dynamic allocation used!"); to your linker script. This will assert that malloc() is not defined.

Neither of these options protect you from redefining global ::new to use some other form of global allocation. You could do the same for global symbol ::new in the linker script, but its name is mangled (in here _Znwj), so this will be a little strange...

like image 129
Freddie Chopin Avatar answered Oct 31 '22 19:10

Freddie Chopin


Regardless of what programming language you use:

On any sound, bare-metal system, you simply remove the .heap segment from the linker script entirely. Any code relying on dynamic allocation will then fail to link. And you won't have to allocate RAM for a segment that you weren't going to use anyway.

like image 28
Lundin Avatar answered Oct 31 '22 19:10

Lundin


There are two things I want to emphasize:

  1. Inclusion of exception related headers with their definitions should not bother you if the exceptions don't find their way into your code.
  2. When you disable the exceptions, you cannot use them in your code (the compilation will fail if you do). However, it doesn't remove usage of exceptions from standard library. The standard library may contain pre-compiled versions of template classes, such as std::string (i.e. std::basic_string<char, ...>) or std::streambuf (i.e. std::basic_streambuf<char, ...>), and when you use it in your code, the compiler doesn't try to instantiate the templates, it just reuses the pre-compiled version with exceptions.

In order to have much better control over your code I strongly recommend to exclude standard library altogether using -nostdlib compilation option with G++ compiler. It won't prevent your from using various template classes, such as std::array from STL, it will just exclude the whole C++ library and runtime for you.

I also recommend reading Practical Guide to Bare Metal C++. It may give a bit of deeper insight into C++ bare-metal internals.

like image 2
Alex Robenko Avatar answered Oct 31 '22 20:10

Alex Robenko