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.
Related
I am new to C++. I try to understand Memory Management in C++ and also to work with pointers.
I have a question about dynamic array.
//This is the part of my code:
int *ptr;
ptr = new int[3];
ptr[0] = 1;
ptr[1] = 2;
ptr[2] = 3;
// Normally I would think I cannot add further elements to the array, but it is possible
ptr[3] = 4;
ptr[4] = 5;
ptr[5] = ...
So, my question is why am I able to add further elements to the array when I initialized the size of Array with size = 3 ?
On the one hand, it makes sense that my array can grow "dynamically". On the other hand it makes no sense because of this line:
ptr = new int[3];
You are not adding new elements into array, you are just overwriting some random patch of memory adjacent to your array.
Accessing an array element is merely accessing a shifted pointer to the first element:
int *ptr;
ptr = new int[3]; // This code allocates 12 bytes, say 0x12340000 - 0x1234000B. ptr = 0x12340000 (note 4 bytes for each integer)
ptr[2] = 5; // This code sets integer at 0x12340000+2*sizeof(int) = 0x12340008
ptr[3] = 6; // This code sets an "integer" at 0x12340000+3*sizeof(int) = 0x1234000C - which is outside your array
ptr[10000000] = 7; // This or something like this will crash your program
You are just lucky this does not lead to a crash - in other circumstances, it would.
General advice: you can't add elements to an array, if you need to change size of a collection later - use vector
I would suggest using vector instead of array.
Exceeding an array bounds is undefined behaviour. That's why.
In this case you are lucky to get the output. But undefined Behavior means that the program can explode your computer next time ;)
So, don't do that.
I've been reading through some books, and when it comes to Class/Functions using Pointers/Dynamic Memory (or heap or w/e they call it) I start to get confused.
Does anyone have a simple....like easy example they can show, because the books im using are using overly complex examples (large classes or multiple functions) and it makes it hard to follow. Pointers have always been my weak point anyways but I understand BASIC pointers, just classes/functions using them is a little bit confusing.
Also.....when would you use them is another question.
Stack allocation:
char buffer[1000];
Here the 1000 must be a constant. Memory is automatically freed when buffer goes out of scope.
Heap Allocation:
int bufsz = 1000;
char* buffer = new char[bufsz];
//...
delete [] buffer;
Here bufsz can be a variable. Memory must be freed explicitly.
When to use heap:
You don't know how much space you will need at compile time.
You want the memory/object to persist beyond the current scope.
You need a large chunk of memory (stack space is more limited than heap space)
Your computer's RAM is a big pile of bytes ordered one after another, and each one of those bytes can be accesed independently by it's address: an integer number startig from zero, upwards. A pointer is just a variable to hold that address of a single place in memory.
Since the RAM is a big chunk of bytes, the CPU ussually divides that big pile of bytes on several chunks. The most important ones are:
Code
Heap
Stack
The Code chunk is where the Assembly code lies. The Heap is a big pool of bytes used to allocate:
Global variables
Dynamic data, via the new operation on C++, or malloc() on C.
The stack is the chunk of memory that gets used to store:
Local variables
Function parameters
Return values (return statement on C/C++).
The main difference between the Stack and Heap is the way it is used. While the Heap is a big pool of bytes, the Stack "grows" like a stack of dishes: you can't remove the dish on the bottom unless there are no more dishes on it's top.
That's how recursion is implemented: every time you call a function recursively, memory grows on the stack, allocating parameters, local variables and storing return values of the returning functions, one on top of the others just like the stack of dishes.
Data living on the Stack have different "Life Span" than the data living on the Heap. Once a function exits, the data on the local variables get lost.
But if you allocate data on the Heap, that data won't get lost util you explicitly free that data with the delete or free() operations.
A pointer is basically a variable that contains the memory address of another variable (or in other cases to a function, but lets focus on the first).
That means that if I declare int[] x = {5,32,82,45,-7,0,123,8}; that variable will be allocated to memory at a certain address, lets say it got allocated on address 0x00000100 through 0x0000011F however we could have a variable which indicates a certain memory address and we can use that to access it.
So, our array looks like this
Address Contents
0x00000100 1
0x00000104 32
0x00000108 82
0x0000010B 45
0x00000110 -7
0x00000114 0
0x00000118 123
0x0000011B 8
If, for example, we were to create a pointer to the start of the array we could do this: int* p = &x; imagine this pointer variable got created a memory address 0x00000120 that way the memory at that address would contain the memory location for the start of array x.
Address Contents
0x00000120 0x00000100
You could then access the contents at that address through your pointer by dereferencing the pointer so that int y = *p would result in y = 1. We can also move the pointer, if we were to do p += 3; the pointer would be moved 3 addresses forward (note, however, that it moves 3 times the size of the type of object it is pointing to, here I am making examples with a 32 bit system in which an int is 32 bits or 4 bytes long, therefore the address would move by 4 bytes for each increment or 12 bytes in total so the pointer would end up pointing to 0x0000010B), if we were to dereference p again by doing y = *p; then we'd end up having y = 45. This is just the beginning, you can do a lot of things with pointers.
One of the other major uses is to pass a pointer as a parameter to a function so that it can do operations on certain values in memory without having to copy all of them over or make changes that will persist outside of the function's scope.
Warning: Don't do this. This is why we have vectors.
If you wanted to create an array of data, and return if from a function, how would you do it?
Obviously, this does not work:
int [10] makeArray(int val)
{
int arr[10];
for(int i=0; i<10; ++i)
arr[i] = val;
return arr;
}
You cannot return an array from a function. We can use pointers to refer to the first element of an array, like this:
int * makeArray(int val)
{
int arr[10];
for(int i=0; i<10; ++i)
arr[i] = val;
return &(arr[0]); // Return the address of the first element.
// Not strictly necessary, but I don't want to confuse.
}
This, however, also fails. arr is a local variable, it goes on the stack. When the function returns, the data is no longer valid, and now you have a pointer pointing to invalid data.
What we need to do is declare an array that will survive even after the function exits. For that, we use keyword new which creates that array, and returns the address to us, which needs to be stored in a pointer.
int * makeArray(int val)
{
int * arr = new int[10];
for(int i=0; i<10; ++i)
arr[i] = val;
return arr;
}
Then you can call that function and use that array like this:
int * a = makeArray(7);
for(int i=0; i<10; ++i)
std::cout << a[i] << std::endl;
delete [] a; // never forget this. Obviously you wouldn't do it right
// away like this, but you need to do it sometime.
Using pointers with new also gives you the advantage that you can determine the size of the array at runtime, something you can't do with local static arrays(though you can in C):
int * makeArray(int size, int val)
{
int * arr = new int[size];
for(int i=0; i<size; ++i)
arr[i] = val;
return arr;
}
That used to be one of the primary purposes for pointers. But like I said at the top, we don't do that anymore. We use vector.
One of the last vestiges of pointers is not for dynamic arrays. The only time I ever use them, is in classes where I want one object to have access to another object, without giving it ownership of that object. So, Object A needs to know about Object B, but even when Object A is gone, that doesn't affect Object B. You can also use references for this, but not if you need to give Object A the option to change which object it has access to.
(not tested, just writing down. and keeping things intentionally primitive, as requested.)
int* oneInt = new int; // allocate
*oneInt = 10; // use: assign a value
cout << *oneInt << endl; // use: retrieve (and print) the value
delete oneInt; // free the memory
now an array of ints:
int* tenInts = new int[10]; // allocate (consecutive) memory for 10 ints
tenInts[0] = 4353; // use: assign a value to the first entry in the array.
tenInts[1] = 5756; // ditto for second entry
//... do more stuff with the ints
delete [] tenInts; // free the memory
now with classes/objects:
MyClass* object = new MyClass(); // allocate memory and call class constructor
object->memberFunction("test"); // call a member function of the object
delete object; // free the object, calling the destructor
Is that what you wanted? I hope it helps.
I think this is what you're asking about:
Basically C++ doesn't allow variable-sized arrays. Any array in C++ has to be given a very specific size. But you can use pointers to work around that. Consider the following code:
int *arry = new int[10];
That just created an array of ints with 10 elements, and is pretty much the same exact thing as this:
int arry[] = int[10];
The only difference is that each one will use a different set of syntax. However imagine trying to do this:
Class class:
{
public:
void initArry(int size);
private:
int arry[];
};
void class::initArry(int size)
{
arry = int[size]; // bad code
}
For whatever reason C++ was designed to not allow regular arrays to be assigned sizes that are determined at runtime. Instead they have to be assigned sizes upon being coded. However the other way to make an array in C++ - using pointers - does not have this problem:
Class class:
{
public:
~class();
void initArry(int size);
private:
int *arry;
};
class::~class()
{
delete []arry;
}
void class::initArry(int size)
{
arry = new int[size]; // good code
}
You have to do some memory cleanup in the second example, hence why I included the destructor, but by using pointers that way you can size the array at runtime (with a variable size). This is called a dynamic array, and it is said that memory here is allocated dynamically. The other kind is a static array.
As far as 2-dimensional arrays go, you can handle it kind of like this:
Class class:
{
public:
~class();
void initArrays(int size1, int size2);
private:
int **arry;
};
class::~class()
{
delete [] arry[0];
delete [] arry[1];
delete [] arry;
}
void class::initArrays(int size1, int size2)
{
arry = new int*[2];
arry[0] = new int[size1];
arry[1] = new int[size2];
}
Disclaimer though: I haven't done much with this language in a while, so I may be slightly incorrect on some of the syntax.
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.
This is a bit unclear to me... So, if I have a function:
char *test(int ran){
char *ret = new char[ran];
// process...
return ret;
}
and then call it multiple times:
for(int i = 0; i < 100000000; i++){
char *str = test(rand()%10000000+10000000);
// process...
// delete[] str; // do i have to delete it here?
}
So the question is, do I have to use delete[] for each new[] call?
You don't have to. But if you don't delete memory you reserved with 'new' you will start running out of memory eventually (memory leak).
Yes you do, otherwise you'll have a memory leak.
It's not the greatest idea to allocate in one function and free in another, though. Why not allocate in the for loop and pass the pointer to test -- this keeps the new and delete together in the code.
The answer was already given, but as you tagged the question as C++, and not as C, this is how you probably want to do it in C++ (of course, there might be other reasons not to, but there is little chance).
vector<char> (int ran){
vector<char> ret(char);
// process...
return ret;
}
And to call it:
for(int i = 0; i < 100000000; i++){
vector<char> str = test(rand()%10000000+10000000);
// process...
}
No new, thus no delete thus no memory leak.
Actually, you also probably want to use std::string instead of char* (I used vector to give a more general example).
Don't worry of data that will be copied. The compiler will optimize it out.
Edit : ok, it might not optimize it out :) however there are big chances it will. And as long there is no performance issues, go for the simplest version.
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