If I have the following lines inside a loop:
Type *unite = new Type(newSize);
or
double *array= new double[anySize];
what is the behavior in what concerns to memory if I don't have delete operators inside it? It will be constantly allocating objects and arrays on different memory locations, and therefore memory leaks?
Yes it will. This:
for (int i = 0; i < 10; ++i)
{
Type* unite = new Type(newSize);
}
will allocate 10 objects of type Type, all at different locations. None of them will be deallocated, and at the end you will not have a pointer to any of them. You will leak 10 * sizeof(Type) bytes of memory.
Similarly, this
for (int i = 0; i < 10; ++i)
{
double *array= new double[anySize];
}
will for the same reason leak 10 * anySize * sizeof(double) bytes of memory.
It will be constantly allocating objects and arrays on different memory locations, and therefore memory leaks?
Assuming you mean this:
for (;x;x)
{
double *ptr = new double[42];
}
Then the answer is yes, the memory is leaked.
Yes. You will leak memory at every iteration of your loop. boost::scoped_ptr and boost::scoped_array are made to handle such situations.
Related
I am working with legacy C++ code that reserves a block of memory using malloc and divides it up into parts that are freed separately. Something like this:
const int N_floats_per_buffer = 100;
const int N_buffers = 2;
//reserve buffers en bloque
float * buffer = (float*) malloc(N_float_per_buffer * N_buffers * sizeof(float));
//then this block memory is divided into sub-blocks
float * sub_buffer[N_buffers];
for(int j = 0; j < N_buffers; ++j)
{
sub_buffer[j] = buffer + j*N_floats_per_buffer;
}
//do something with the buffers...
//...
//finally: memory is freed for the individual buffers
for(int j = 0; j < N_buffers; ++j)
{
if(sub_buffer[i]!=NULL) free(sub_buffer[j]);
}
It is actually even more confusing in the real code but I think I have captured the essence of it.
My question is: is that a memory leak?
It is not a memory leak. It is worse, undefined behavior.
You can only call free on a pointer returned from malloc (or calloc, etc.). You are not allowed to call free on a pointer pointing somewhere else in the returned storage block. Doing that causes undefined behavior.
Also on a more pedantic side, malloc does not create any objects and pointer arithmetic requires the pointer to point to an element of an array object for it to have well-defined behavior in C++. Therefore you technically already have undefined behavior when you do
buffer + j*N_floats_per_buffer
although probably all compilers behave as expected (even though the standard made no guarantees). This was only resolved recently for C++20, where the required array will be created implicitly.
One should almost always only use new/delete, not malloc/free in C++.
I used the malloc function for allocating 10^9 memory locations as part of an array.
The Code 1 gets executed successfully.
Code 1:
int main(){
int size = (int)(1e9);
int* arr = (int*) malloc( size * sizeof(int) );
for(int i=0;i<size;i++){
arr[i] = i;
}
return 0;
}
But when I tried to access the particular memory location or index value = 12345678 (which is < 1e9), I got segmentation fault
Code 2:
int main(){
int size = (int)(1e9);
int* arr = (int*) malloc( size * sizeof(int) );
for(int i=0;i<size;i++){
arr[i] = i;
}
cout<<arr[12345678]<<endl; //added this line of code, which gives segmentation fault
return 0;
}
My guess is, this occurs due to memory fragmentation, but I am not sure about this. Can anyone kindly explain the correct reason.
It's definitely
Compiler optimisation
Limit on memory allocation as per standard sandbox
Modern operating systems are doing something called "lazy allocation", this means that when you ask to allocate memory, they give it to you without actually allocating the memory.
This is exactly the reason for the Virtual memory vs Physical memory taken you see while using top.
The memory is only really allocated when you try to use the buffer itself.
In your example, you've allocated a lot of memory (4GB), the OS let you allocate it but did not actually free up the memory needed for it, once you've tried using it, it tried to actually provide the memory you asked for, couldn't do it, and therefore crashed.
I wrote a basic custom memory management allocator which would grab a chunk of memory, pre-create X objects so that whenever I needed to "create" an object I could grab one of the pre-created ones and simply assign data members (memory was already allocated).
I used placement-new:
//Grab a chunk of memory
char* buf = new char [sizeof(X) * num_objs];
//Pre-create a lot of objects
for(std::int64_t i=0; i<num_objs; i++){
char* c = buf + (sizeof(X) * i);
//This line creates the Order object at location c
X* x = new(c)X;
}
//Assign data members to objects
for(std::int64_t i=0; i<num_objs; i++){
char* buf_loc = buf + (sizeof(X) * i);
X* my_x = reinterpret_cast <X*> (buf_loc);
my_x->a = 1;
my_x->b = 2;
my_x->c = 3;
my_x->d = 4;
}
How easy/practical would it be to change the above and directly grab memory from the OS using brk()?
Using brk will probably interfere with the regular C/C++ memory allocator. Even if you don't use regular new or malloc() in your code, it might be used in libraries.
If you want to manage your own memory, use mmap() on /dev/zero to get an empty block of memory. I think you can do this repeatedly to get new blocks.
Note that the question has been changed and no longer matches the answers
I'm trying to create memory to hold a buffer of floats (here, 4 floats).
I've allocated the memory, and all the 4 values in the memory are zero.
The loop of course iterates 4 times, but the 4th time moves ptr to outside the memory that I've allocated. So at the end of the loop I move ptr back to where I allocated the memory, and use delete[].
My question is: Is the entire 4-float buffer being deleted when I call delete[]? (this is obviously what I need!)
int inFramesToProcess = 4;
float *ptr = new float[inFramesToProcess]();
for(UInt32 i = 0; i < inFramesToProcess; ++i) {
ptr++;
}
ptr -= inFramesToProcess;
delete[] ptr;
Copy the pointer before you increment it.
int inFramesToProcess = 4;
float *ptr = new float[inFramesToProcess]();
float *ptr_copy = ptr;
for(UInt32 i = 0; i < inFramesToProcess; ++i) {
ptr_copy++;
}
delete[] ptr;
Or just don't use pointers for dynamic arrays, use a vector instead. Then you don't have to worry about deleting.
You can't.
You can only delete the value you get from new. Keep the original pointer.
General rule:
Try hard to avoid modifying pointers at all times, no matter how clever/professional/"brilliant" it looks. There's really no reason to (you're welcome to prove me wrong). Use subscripts instead; they're more readable and easier to debug, and they avoid these kinds of issues.
I am wondering about the delete[] operator in C++. (I am using Visual Studio 2005).
I have an unmanaged DLL that is being called by a managed DLL. When I close this program after performing a few tasks while debugging, I am getting many (thousands?) of memory leaks, mostly 24 bytes - 44 bytes in size.. I suspect it might be due to a certain unmanaged DLL I have.
Anyway, from what I understand, if I have the following code:
char* pointer = new char[500]
/* some operations... */
delete[] pointer;
Then all the memory for it is freed up correctly, am I right?
What happens when I have the following code:
char* pointer = new char[500];
char* pointerIt = pointer;
/* some code perhaps to iterate over the whole memory block, like so */
for (int i = 0; i < 250; i++){ // only iterate halfway
*pointerIt = 0;
pointerIt++;
}
delete[] pointer;
The memory pointed to by pointer is deleted right? So it means that pointerIt is now not pointing to valid memory.. But that's ok because I can set both pointers to NULL, right?
Anyway, what happens now if I do this:
char* pointerFirstPosition = new char[500];
char* pointerIt = pointerFirstPosition;
for (int i = 0; i < 250; i++){ // only iterate halfway
*pointerIt = 0;
pointerIt++;
}
delete[] pointerIt; // delete the pointer iterator...
Will this code delete the memory block pointed to by pointerIt up to pointerIt +500? or will it delete the memory block pointed to by pointerFirstPos to pointerFirstPos +500?
Could this result in a memory leak?
Sorry for the long winded message, I'm trying to get my message across clearly.
Thanks,
kreb
First question set:
char* pointer = new char[500]
/* some operations... */
delete[] pointer;
Then all the memory for it is freed up
correctly, am I right?
right.
Second question set:
char* pointer = new char[500];
char* pointerIt = pointer;
/* some code perhaps to iterate over the whole memory block, like so */
for (int i = 0; i < 250; i++){ // only iterate halfway
*pointerIt = 0;
pointerIt++;
}
delete[] pointer;
The memory pointed to by pointer is
deleted right? So it means that
pointerIt is now not pointing to valid
memory.. But that's ok because I can
set both pointers to NULL, right?
The memory pointer holds an address to is fully delted yes. Both pointer and pointerIt hold an address to invalid memory. Each pointer is simply a variable, and every variable is independent. So both store their own address independent of each other. The dereference operator * will simply give you the variable at that address. The variable at that address is a different variable than the pointer variable.
Third question set:
You should be deleting only the address that was allocated, the whole array. You'll have undefined results if you try to delete a partial array. Could it result in a memory leak? Possibly, could it result in a crash? Possibly, could it result in ....? Possibly.
So only delete what you allocate. If you allocate an array then you delete with delete[] if you delete a type that is not an array you delete with delete.
Here is an eample of something that is fine just for clarity:
char* pointer = new char[500];
char* pointerIt = pointer;
//This is fine because you are deleting the same address:
delete[] pointerIt;
//The memory that both variables point to is freed, do not try to free again
check out boost::shared_ptr or boost::scoped_ptr and NEVER worry about this again.
This gives you a static & reference counted way to manage your memory.
http://www.boost.org/doc/libs/1_39_0/libs/smart_ptr/shared_ptr.htm