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!
do I need to alter the code in any way to handle alignment issues?
Yes.
do I need to do anything special to handle memory alignment?
Yes.
uint8_t conceptually represents an unsigned integer with 8 bits. Use char or unsigned char to represent 1 byte.
Anyway, use operator new with size and alignment:
auto maxsize = max_of_3(sizeof(A), sizeof(B), sizeof(C)),
auto neededalign = std::align_val_t(max_of_3(alignof(A), alignof(B), alignof(C));
void *buffer = operator new(maxsize, neededalign);
or statically:
std::aligned_storage<
max_of_3(sizeof(A), sizeof(B), sizeof(C)),
max_of_3(alignof(A), alignof(B), alignof(C))> buffer;
A *stuff = new(buffer.data) A;
A buffer obtained from malloc is guaranteed to be correctly aligned for any basic type, but I am unsure whether a pointer obtained from new is, so I would prefer:
uint8_t *buffer = malloc(max_size); // delete it later with free
But you could even get rid of any dynamic allocation by building a custom buffer using alignas:
// only required for C++11, starting from C++14, std::max is constepr
constexpr size_t max3(size_t i, size_t j, size_t k) {
uint32_t max_size = i;
max_size = (i > j) ? i : j;
max_size = (k > max_size) ? k : max_size;
return max_size;
}
// declare a custom struct with required size and alignment
struct alignas(max3(alignof(A), alignof(B), alignof(C))) Buffer {
char buffer[max3(alignof(A), alignof(B), alignof(C))];
};
// build a statically allocated buffer of correct size and alignment
Buffer buffer;
From that point on, you can safely inplace construct an object in buffer and of course explicitely destroy it before re-using the memory.
Related
I have a project in which I have to allocate 1024 bytes when my program starts. In C++ program.
void* available = new char*[1024];
I write this and I think it is okay.
Now my problem starts, I should make a function that receives size_t size (number of bytes) which I should allocate. My allocate should return a void* pointer to the first bytes of this available memory. So my question is how to allocate void* pointer with size and to get memory from my available.
I'm a student and I'm not a professional in C++.
Also sorry for my bad explanation.
It looks like you're trying to make a memory pool. Even though that's a big topic let's check what's the minimal effort you can pour to create something like this.
There are some basic elements to a pool that one needs to grasp. Firstly the memory itself, i.e. where do you draw memory from. In your case you already decided that you're going to dynamically allocate a fixed amount of memory. To do it properly the the code should be:
char *poolMemory = new char[1024];
I didn't choose void* pool here because delete[] pool is undefined when pool is a void pointer. You could go with malloc/free but I'll keep it C++. Secondly I didn't allocate an array of pointers as your code shows because that allocates 1024 * sizeof(char*) bytes of memory.
A second consideration is how to give back the memory you acquired for your pool. In your case you want to remember to delete it so best you put it in a class to do the RAII for you:
class Pool
{
char *_memory;
void *_pool;
size_t _size;
public:
Pool(size_t poolSize = 1024)
: _memory(new char[poolSize])
, _pool(_memory)
, _size(poolSize)
{
}
~Pool() { delete[] _memory; } // Forgetting this will leak memory.
};
Now we come to the part you're asking about. You want to use memory inside that pool. Make a method in the Pool class called allocate that will give back n number of bytes. This method should know how many bytes are left in the pool (member _size) and essentially performs pointer arithmetic to let you know which location is free. There is catch unfortunately. You must provide the required alignment that the resulting memory should have. This is another big topic that judging from the question I don't think you intent to handle (so I'm defaulting alignment to 2^0=1 bytes).
#include <memory>
void* Pool::allocate(size_t nBytes, size_t alignment = 1)
{
if (std::align(alignment, nBytes, _pool, _size))
{
void *result = _pool;
// Bookkeeping
_pool = (char*)_pool + nBytes; // Advance the pointer to available memory.
_size -= nBytes; // Update the available space.
return result;
}
return nullptr;
}
I did this pointer arithmetic using std::align but I guess you could do it by hand. In a real world scenario you'd also want a deallocate function, that "opens up" spots inside the pool after they have been used. You'd also want some strategy for when the pool has run out of memory, a fallback allocation. Additionally the initially memory acquisition can be more efficient e.g. by using static memory where appropriate. There are many flavors and aspects to this, I hope the initial link I included gives you some motivation to research a bit on the topic.
I have a class which allocates array of fixed buffer as below.
class CMyBuffer
{
public:
CMyBuffer() { /* constructor ... */ }
~CMyBuffer() { /* destructor ... */ }
int copy(char *source, int len);
char m_szBuf[MYBUF_SIZE * sizeof(char)];
int m_nLen;
};
When an object of this class is created, there would be memory allocation for the object including the fixed buffer of size MYBUF_SIZE. So as to say there would be one call to malloc() [In good old 'C' thinking].
I was wondering if it is possible to vary the buffer size based on constructor parameter. Of course, it is possible if we make m_szBuf a pointer and allocate memory in the constructor based on the constructor parameter (which specified size). But I think this would end up calling memory allocation twice (once for the object overall and once for the pointer to the buffer within the object). Is there a way to vary the buffer size in the object but with only one call to memory allocation? The concern for exploring this approach is to reduce heap memory fragmentation.
So as to say there would be one call to malloc() [In good old 'C'
thinking].
You are writing c++, not c, right?
In c++ arrays with a size that is only known at runtime are std::vectors. For someone used to get their hands dirty it might be a bit lame, but as a matter of fact you really need very good reasons not to use std::vector. It is rare that std::vector cannot do what you need for a dynamic array.
I was wondering if it is possible to vary the buffer size based on
constructor parameter.
Yes, of course:
class CMyBuffer
{
public:
CMyBuffer(size_t size) : m_szBuf(size) { /* constructor ... */ }
~CMyBuffer() { /* destructor ... */ }
int copy(char *source, int len);
std::vector<char> m_szBuf;
};
You also do not need to keep track of the size of the vector yourself (that is c-thinking ;).
Maybe you think, well std::vector is fine, but it does not help me because I still need a char* in some places of my code. However, std::vector can give you access to the underlying array via std::vector::data().
If you only have a few expected sizes of buffer, and they're known at compile time, you can use templating to generate classes for each size:
template <size_t N>
class CMyBuffer
{
public:
char m_szBuf[N * sizeof(char)];
int m_nLen = N;
};
// usage
CMyBuffer<MYBUF_SIZE> buff;
CMyBuffer<256> buffBig;
i have some complex classes in my xcode project (below a generic example)
and it seems I have hit some sort of data size limit.
the array sizes I need do not work, if I reduze the array sizes the code works (so no programming errors), but it is too small for what I planned.
reading through the internet I figured out it must be a problem with stack size and most of the solutions say "convert your static arrays to dynamic arrays".
but (1) that is not that easy with multidimensional arrays (some up to 5 to 10 dimensions as they monitor multiple independent variables and each combination is possible)
and (2) are most of the arrays nested in several classes, making it even worse.
I thought already of reducing the data
int instead of long with some intelligent transposition...
change resolution of c (0-100%) into steps of 10% (so [100] reduces to [10])
but on one hand this might jeopardize the overall results and on the other is the project still at the start so it will grow in the next month... this array size problem will come back sooner or later...
here I generalized the code showing a 4 dimensional array (2x 2D).
I guess most professional programs use arrays that are even bigger.
so there must be a way to make this works...
//.h
class StatisticTable
{
public:
long Array1 [100][50];
long Array2 [100][50];
long Array3 [100][140];
};
class Statistic
{
public:
void WriteStatistic(short Parameter_a, short Parameter_b,
short Parameter_c, short Parameter_d);
short ReadStatistic(short Parameter_a, short Parameter_b,
short Parameter_c, short Parameter_d);
private:
StatisticTable Table[16][8];
};
//.cpp
void WriteStatistic(short a, short b, short c, short d)
{
for (int i=0; i<d, i++) {Table[a][b].Array1[c][i]++;}
for (int i=d; i<50, i++) {Table[a][b].Array2[c][i]++;}
//write some more stuff
return;
}
Can you use heap allocation instead of stack allocation?
As suggested, using std::unique_ptr:
auto const ptr = std::unique_ptr<StatisticTable>(new StatisticTable()).get(); // heap allocated and deleted automatically when obj goes out of scope
I.e.
auto obj = new StatisticTable(); // heap allocation, allocate reference to new StatisticTable object on heap
// code
delete obj; // release heap allocated object
vs.
auto x = StatisticTable() // stack allocation
Consider the following code
struct foo
{
const int txt_len;
const int num_len;
char * txt;
int * num;
foo(int tl, int nl): txt_len(tl), num_len(nl)
{
char * tmp = new char[txt_len * sizeof(char) + num_len * sizeof(int)];
txt = new (tmp) char [txt_len * sizeof(char)];
num = new (tmp + txt_len * sizeof(char)) int[num_len * sizeof(int)];
// is this the same as above?
// txt = tmp;
// num = (int *) (tmp + txt_len * sizeof(char));
}
~foo()
{
delete[] txt; // is this the right way to free the memory?
}
};
I want *txt and *num to be contiguous, is that the best way to do it?
also is there any difference between placement new and pointer arithmetic? which one should I use?
If you want a contiguous block of memory, you have to allocate it whole with a single call to operator new[] or malloc() or similar. Multiple calls to these functions do not guarantee any contiguity of allocated blocks whatsoever. You may allocate a big block and then carve parts from it as needed.
And you should delete and free() all blocks previously allocated with new and malloc(), otherwise you'll leak memory and probably make your program unstable (it will fail to allocate more memory at some point) and exert unnecessary pressure on memory in the OS, possibly slowing down other programs or making them unstable as well.
Placement new, however, does not actually allocate any memory. It simply constructs an object at the specified location and so you don't need to free that memory twice.
One problem that I see in your code is that it doesn't align ints. On some platforms reading or writing integers bigger than 1 byte from/to the memory must be aligned and if it's not, you can either read/write values from/to wrong locations or get CPU exceptions leading to termination of your program. The x86 is very permissive in this regard and won't mind, though may tax you with degraded performance.
You'll need to put the int data first, due to the alignment issues. But we can't then do delete num[] as the type is wrong - it must be cast to a char* before deleting.
char * tmp = new char[num_len * sizeof(int) + txt_len * sizeof(char)];
num = new (tmp) int[num_len];
txt = new (tmp + num_len * sizeof(int)) char [txt_len];
(This makes liberal use of the fact that sizeof(char)==1)
You might be tempted to do delete[] num, but num is of type int*, and it was new'ed as a char*. So you need to do;
delete[] (char*) num;
This is the same as long as you use POD types. And your delete is fine.
However, as David's comment states, you need to consider alignment problems.
Placement new is mostly use when you want to call constructor of class/struct on some preallocated memory blocks.
But for native types it makes no different to use placement new & pointer arithmetic.
Please correct me if I was wrong.
If txt and num always point to int and char, other built in types or other types not requiring construction, then no. You don't need placement new.
If on the other hand you were to change one of them to a class which requires construction, i.e. changes txt to type std::string, then using placement new is necessary.
Placement new allows you to call the constructor, building, if you like, the object at that address. Built in types have default constructors that do nothing if your not initializing.
In both cases you need to do pointer arithmetic, just one way you store the answer in a pointer, the other you pass the answer to placement new which gives it back to you for storage in the pointer, and then calls the constructor.
struct Test
{
int var;
char *arr;
}
int main()
{
Test a;
a.arr = new char[50];
}
The above code would create a dynamic array in the structure but the dynamic array would not be actually memory allocated within the structure, its memory would be allocated somewhere else. I want this array to be allocated in the structure as with the fixed array but I don't want to use fixed array. Any ideas?
I've tried my best to clarify my question, hope you understand.
I want to send this structure through UDP and UDP takes continues memory buffer to send that's why I want this structure to have continuous memory.
You can not do that as the new memory is from heap/ free store and your a will be allocated on stack....
you can allocate using malloc/new a continous memory block of sizeof Test + your required size and make the pointer arr to point at the end of the Test structure.
If you need it in function scope on stack you can use alloca.
Test *a = (Test*)alloca(sizeof(Test)+yoursize);
a->arr = (char*)a+sizeof(Test)...
No you cannot have variable length arrays in C++.
So you cannot do that.
You can have a fixed length array or you can use the approach you have given.
Another approach is,
You can use placement new to place your array at an pre-allocated memory location. This memory could be on stack.
Your code don't compile. You should compile it with all warnings enabled, and improve it till you got no warnings. And are your studying C or C++? If it is C++, consider using std::vector
struct Test {
int var;
char arr[1];
};
int main()
{
std::vector<char> buf;
buf.resize(sizeof(Test) + 50);
Test *foo = reinterpret_cast<Test *>(&buf[0]);
foo->arr[40] = 'b';
}
You can pass array size to structs constructor and allocate memory for array there. Don't forget to deallocate it somewhere, e.g. in destructor:
struct Test
{
int m_var;
char *arr;
public:
Test(int var) : m_var(var)
{
arr = new char[m_var];
}
~Test()
{
delete[] arr;
arr = 0;
}
};
void main(int argc, char* argv[])
{
Test t(50);
return 0;
}
Although it hasn't been "blessed" like it has in C, most compilers will still let you use the "struct hack":
struct variable_array {
size_t size;
char data[1];
};
The "trick" is that when you allocate it, you allocate enough space for the data you want to store (but this means it must be dynamically allocated):
variable_array *a = (variable_array *) ::operator new(sizeof(*a) + data_size);
a->size = data_size;
In theory, this isn't required to work -- the compiler could do a bound-check on references to the data member to ensure you don't index beyond the one element you've defined it to hold in the struct definition. In reality, I don't know of a single compiler that does such a thing, and kind of doubt that such a thing exists. Quite a lot of C code has done things like this for years, so a compiler that did such a check just wouldn't work with a lot of real-world code, even though the standard allows it. C99 also adds this (with minutely different syntax) as an official feature of the language.
Bottom line: it's a bit clumsy, but the possibility of really not working is almost entirely theoretical.
Not truly dynamic allocation, but might solve your problem (depends on if you always know the desired size of the array at compile time)
template <size_t ArraySize>
struct Test
{
int var;
char arr[ArraySize];
}
int main()
{
Test<50> a;
}