I am working on an application which is running on a SAMD21 microcontroller. For those unfamiliar with the SAMD21, it contains an ARM Cortex-M0+ processor. The specific model I am using has 32 kB of RAM. My application is running up to the limits of that 32 kB, so I've been working on optimizing the code for memory usage.
One optimization I've been working on is reducing heap fragmentation. For example, I may have a scenario such as the following:
A *my_obj = new A();
B *my_second_obj = new B();
delete A;
C *my_third_obj = new C();
In the above example, when instantiating my_third_obj
, the memory allocator may attempt to place it in the empty location that was initially being used by my_obj
. However, if my_third_obj
doesn't fit in that spot, then the memory allocator will simply allocate some more space at the top of the heap and move the heap pointer. This will leave a "hole" where my_obj
was located (which may be filled later by other objects), but this creates heap fragmentation.
In my specific application, I've determined that I will ever only need one active instance of classes A, B, or C at any point in time. Because of this, I was thinking about creating a block of memory which holds the current instance of any of those classes, and simply making the memory block as big as the largest class so that it can hold any of the classes. This would reduce heap fragmentation since there would always be a specific place in memory where I would be allocating these specific classes.
Here's a simple example of what I am thinking:
uint32_t max_size = sizeof(A);
max_size = (sizeof(B) > max_size) ? sizeof(B) : max_size;
max_size = (sizeof(C) > max_size) ? sizeof(C) : max_size;
uint8_t *buffer = new uint8_t[max_size];
//Some time later in the program...
C *my_obj = new(buffer) C();
//Some time later in the program...
my_obj->~C();
my_obj = NULL;
memset(buffer, 0, sizeof(max_size));
B *my_other_obj = new(buffer) B();
I've never really used placement new in previous code that I've written, but I think it would be useful in my current circumstance. My main question here is: given the example that I've laid out, do I need to alter the code in any way to handle alignment issues? Classes A, B, and C all have different member variables and different sizes. Will this code just "work", or do I need to do anything special to handle memory alignment?
Thanks!
Yes.
Yes.
uint8_t
conceptually represents an unsigned integer with 8 bits. Usechar
orunsigned char
to represent 1 byte.Anyway, use
operator new
with size and alignment:or statically: