I would like to ask a question concerning dynamic memory allocation in C++.
I understand that the nature of the problem I am about to propose is easy to resolve using simple C++ techniques, but for this particular exercise I have to use a more C-like approach.
Let me set an example:
I have the following structs:
typedef struct A{
B *b;
int a;
}
typedef struct B{
C *c;
int x;
}
typedef struct C{
int y;
}
And let's assume this main:
int main(){
A test;
test.a = 1;
test.b = (B*)calloc(2,sizeof(B));
test.b[0].c = (C*)calloc(2,sizeof(C));
test.b[0].x = 2;
test.b[0].c[0].y = 3;
test.b[0].c[1].y = 4;
test.b[1].c = (C*)calloc(2,sizeof(C));
test.b[1].x = 5;
test.b[1].c[0].y = 6;
test.b[1].c[1].y = 7;
}
So my question is as follows:
What happens?
Is there a possibility the memory blocks allocated for test.b[i].c to overlap with the memory blocks that have been previously allocated for test.b?
If that is possible to happen how can I prevent it from happening?
If it is not possible can you explain exactly how calloc() allocates memory? I would really appreciate a numeric example.
Is there a possibility the memory blocks allocated for test.b[i].c to overlap with the memory blocks that have been previously allocated for test.b?
No.
If that is possible to happen how can I prevent it from happening?
It can't happen, so don't worry.
If it is not possible can you explain exactly how calloc() allocates memory?
Every time you call calloc, it gives you back a pointer to a block of zero-initialized memory large enough to hold the requested number of objects, or NULL if it fails. As long as you don't get NULL back, you have nothing else to worry about.
I'm not sure what you mean by "numeric example".
Related
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.
int a[10];
The above code will create a array of four int variable sizes & thus the programme will be able to store only 4 integers.
Now consider the following commands
int *a,*b,*c,*d;
a= (int *)malloc(sizeof(int));
b= (int *)malloc(sizeof(int));
c= (int *)malloc(sizeof(int));
d= (int *)malloc(sizeof(int));
The above part of code will create four int type pointer & will allocate them memory of int size.
I learnt that dynamic memory allocation allocates memory at rum time.
I want to know that irrespective of using array or malloc(dynamic memory allocation), the user will be getting only four int sized space to store.If we rule out that it is a pointer variable with int size memory, then what will be the use of dynamic memory allocation.In both cases , the user will get only four int spaces & to get more he will need to access the source code.So why do we use malloc or dynamic memory allocation ?
Consider
int a,*b;
cin >> a;
b= (int *)malloc(a*sizeof(int));
The user types a number a and gets a ints. The number a is not known to either to programmer or the compiler here.
As pointed out in the comments, this is still bad style in C++, use std::vector if possible. Even new is still better than malloc. But i hope the (bad) example helps to clarify the basic idea behind dynamic memory allocation.
You're right that it's all just memory. But there is a difference in usage.
In the general case, you don't necessarily know ahead of time the amount of memory you will need and then time when such memory can be safely released. malloc and its friends are written so that they can keep track of memory used this way.
But in many special cases, you happen to know ahead of time how much memory you will need and when you will stop needing it. For example, you know you need a single integer to act as a loop counter when running a simple loop and you'll be done with it once the loop has finished executing. While malloc and its friends can still work for you here, local variables are simpler, less error prone and will likely be more efficient.
int a[10];
The above line of code will allocate an array of 10 int's of automatic storage duration, if it was within a local scope.
int *a,*b,*c,*d;
The above, however, will allocate 4 pointers to int also of automatic storage duration, likewise if it was within a local scope.
a= (int *)malloc(sizeof(int));
b= (int *)malloc(sizeof(int));
c= (int *)malloc(sizeof(int));
d= (int *)malloc(sizeof(int));
And finally, the above will allocate int variable per each pointer dynamically. So, every pointer of the above will be pointing to a single int variable.
Do note that dynamically allocated memory can be freed and resized at runtime unlike static memory allocation. Memory of automatic storage duration are freed when run out of scope, but cannot be resized.
If you program in C, casting the result of malloc is unnecessary.
I suggest you to read this: Do I cast the result of malloc?
Then what your doing in your code with the 4 pointers is unnecessary; in fact you can just allocate an array of 4 int with one malloc:
int *a;
a = malloc(4 * sizeof(int));
I'm having trouble understanding arrays of pointers to structures. I created this simple example to try and understand them better. Although it compiles, I keep getting "BAD ACCESS" crashes (nonsense pointers) at the point shown below. Can anyone explain why this is wrong?
#include <iostream>
using namespace std;
struct complex_num {
double real_part;
double imag_part;
};
void init_complex(complex_num *element) {
element->real_part = -1.0; // <--- EXECUTION STOPS HERE.
element->imag_part = 1.0;
}
int main(int argc, char *argv[]) {
int n = 5;
complex_num *array[n]; // Allocates for an array of n pointers to
// the complex_num structure, correct?
for (int i = 0; i < n; i++) {
init_complex(array[i]);
}
return 0;
}
I know there are better ways to do this. I know this is very C in style. Please don't suggest a different data structure. I'm curious specifically about arrays of pointers to structures. Thanks!
You did not allocate memory for your complex_num objects, only for an array with pointers to it. So when you call init_complex, it operates on a pointer to an invalid location.
Try this:
for (int i = 0; i < n; i++) {
array[i] = new complex_num();
init_complex(array[i]);
}
Your statement complex_num *array[n] creates an array of n pointers to complex_num. Meaning, the array can hold n pointers to complex_num; but the pointers themselves are still uninitialized. They point to random locations - every uninitialized primitive (to which pointers belong as well) in C++ will usually simply contain whatever value was in the memory location before the allocation. This will almost certainly lead to unexpected results, as there is no way (or at least no reasonably easy way) of telling where an uninitialized pointer points to.
So you'd have to make each pointer in the array point to some properly set up memory location containing complex_num; only after that you should access (read or write) the values in the complex_num where the pointer points to. To make it e.g. point to a dynamically allocated, new complex_num object, use the above code (notice the new keyword which does the dynamic allocation).
Side note: "Raw" pointers, pointing to dynamically allocated objects, like shown above, are tricky to handle (you should not forget to call delete after you are finished, otherwise you will leak memory), therefore the recommended practice is usually to use smart pointers (like std::shared_ptr, introduced with C++11).
yes, there is no memory allocated to the pointers you have declared. It doesn't point to any valid structure object
what is the difference between the following block of code :
#include<iostream>
using namespace std;
int main()
{
int *p;
float *q;
cout<<p<<"\n"<<q;
}
and this code :
#include<iostream>
using namespace std;
int main()
{
int *p;
float *q;
p = new int;
q = new float;
cout<<p<<"\n"<<q;
}
In both the cases the pointers are allocated some memory right?
Then why should i use the new operator?
No, int *p and float *p declare pointers, but they are not initialised, so they each point to a random address in memory. In particular, they do not point to memory space allocated to your program.
The second piece of code correctly allocates memory and stores the address of that memory in the two pointers. However, note that your code never de-allocates the memory, so you have a memory leak. You'd have to use delete p and delete q at the end of the program to avoid this.
To answer the question in your title a bit more directly: no, you do not have to use the new operator very often in C++; in fact, in well written code you usually use it quite rarely.
In this case, rather than using pointers at all, you would typically want to just define the int and float using the auto storage class, without defining any pointers or using new at all. While you're at it, most code shouldn't have using namespace std; in it either. Fixing those, you could end up with something like this:
#include<iostream>
int main()
{
int p = 1;
float q = 2.0f;
std::cout<<p<<"\n"<<q;
}
If your code has new and/or T *xxx very often (where T is some type and xxx is some identifier) chances are pretty good that it's not really a question of whether you're doing something wrong, only of how many things and how badly wrong.
In the first block of code, memory is allocated for the pointers themselves, but no memory is allocated which they can point to and validly use. The address that is printed out is not safe for your program to use.
The "pointer" variable does already being allocated in main() stack, 4 bytes in 32-bit or 8 bytes in 64-bit machines. The memory storage for int and float, which are pointed by p and q respectively, are not allocated yet in the first case. Your cout just prints out the memory address of p & q, not the value where p or q points to.
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;
}