Bare metal without a global operator

Consider security software in which dynamic allocation is generally prohibited and exceptions are prohibited. Dynamic allocation is only allowed if class explication defines the new and delete operator. Using the new operator for another class should cause compilation to fail.

The easiest way to cause compilation to fail in the described situation is to delete the global new statement:

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

On the one hand, it causes side effects with the standard library. For example, the inclusion of <array> applies to <new_allocator> to <stdexcept> . <new_allocator> uses the ::new operator, and this reason for the failure to fail even when you do not want to use memory allocation and allocation. According to Scoot Meyers, <array> should be bare metal.

On the other hand, this causes an error with the built-in compiler 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 a solution to ban ::new and use <array> ?

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

+5
source share
3 answers

If you are using GCC and GNU LD, I think you can just add --wrap=malloc to your linker flags. Since 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 connection will fail.

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

None of these options will protect you from overriding the global ::new to use any other form of global distribution. You can do the same for the global symbol ::new in the script builder, but its name is garbled (here _Znwj ), so this will be a little weird ...

+4
source

No matter what programming language you use:

On any sound system with exposed metals, you simply delete the .heap segment from the script builder completely. Any code based on dynamic allocation will not be bound. And you do not have to allocate RAM for a segment that you are not going to use in any case.

+3
source

I want to emphasize two things:

  • Including headers associated with exceptions with their definitions should not bother you if exceptions do not get into your code.
  • When you turn off exceptions, you cannot use them in your code (compilation will fail if you do). However, it does not remove the use of exceptions from the 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 does not try to create template instances, it just reuses the pre-compiled version with exceptions.

To have much better control over your code, I highly recommend that you completely exclude the standard library using the -nostdlib compilation -nostdlib with the g ++ compiler. This will not stop you from using various template classes such as std::array from STL, it will simply exclude the entire C ++ library and runtime for you.

I also recommend reading the Bare Metal C ++ Tutorial . This may give a slightly deeper understanding of the internal properties of C ++.

+2
source

Source: https://habr.com/ru/post/1262173/


All Articles