C++: How are pointers themselves handled regarding memory management? - c++

I have a fairly simple question;
I have arrays which contain pointers to objects. I sometimes create mutated arrays from those arrays and only use them, let's say, within a method. Aftwards I don't need them. In this case I don't want the pointed data to be destroyed as I keep using the original Array. What I don't fully understand is what happens to the pointers ( not the data itself, but the pointers) that were created in my temporarily Array? How does Memory deal with them. As far as I know Pointers can only point to an address. You can't "delete" them.
Anyone who can give me more insight? All this time I feel like I'm doing something wrong with memory.
In this case list is my "bag", which is an object wrapper for an array implementation. However since it contains gabs between indexes I use getGapless to get a bag where the nullptr indexes are excluded.
I delete my bag at the end, but it doesn't delete the actual content ( that is done with a different method ).
So when do those pointers in my "players" bag go out of scope?
virtual void processEntities(artemis::ImmutableBag<artemis::Entity*>& bag)
{
artemis::Bag<artemis::Entity*> * list = (artemis::Bag<artemis::Entity*>*)this->world->getGroupManager()->getEntities("HUMAN");
if(list == nullptr) return;//Kill function
artemis::Bag<artemis::Entity*> * players = list->getGapless();
for(int i=0; i<players->getCount(); i++)
{
for(int j=i+1; j < players->getCount(); j++)
{
if(intersects(*players->get(i),*players->get(j))){
std::cout << "Collide YEAH \n";
}
}
}
delete players;
}

Nope, don't worry! You can think of pointers as being managed in the same way as ints or doubles (at least in terms of memory). The pointer itself is like an int that happens to contain the address of some other object or array of objects. Once the pointer disappears from scope, the memory for the pointer itself will automatically be recovered.
The exception would be if you're doing something like int** p = new int*[1], i.e. creating pointers with new. Then you will at some point need to delete p.
If you're creating your pointers like int* p = new int[size]; (which is probably what you want), then p itself is on the stack, which means you don't need to concern yourself with memory deallocation, but the array p points to is on the heap which means you will need to deallocate it at some point.

Pointers are ordinary variables. They are not handled in any special way. There's no difference between pointer variables and integer variables in that respect, as there's no difference between between pointer arrays and integer arrays in that respect.
The memory management for all variables in the language is entirely up to you. If you declare a local variable, it is automatically destroyed when control goes out of its block. If you allocate/create objects dynamically, then you have to deallocate/destroy them explicitly. And so on. There's absolutely nothing special about pointers. They are just like any other variables.
Basically, it is not clear why you are even asking this question, since the issue your question seems to address does not really exist. Can you provide an example of what caused you to ask this?

Pointers just hold addresses, the same way 'int' holds an integer. If you instead had an array of ints and you were using a mutated array based on it, then got rid of the mutated array, the original array stays untouched; here it is really no different.
The values in the mutated array go away, but since they are copies (regardless of whether they are ints or pointers or whatever), it does not affect the original.

Related

Problem in Deleting the elements of an array allocated with new[]

This question is similar to Problem with delete[], how to partially delete the memory?
I understand that deleting an array after incrementing its pointer is not possible as it loses the track of how many bytes to clean. But, I am not able to understand why one-by-one delete/deallocation of a dynamic array doesn't work either.
int main()
{
int n = 5;
int *p = new int[n];
for(int i=0;i<n;++i){
delete &p[i];
}
}
I believe this should work, but in clang 12.0 it fails with the invalid pointer error. Can anyone explain why?
An array is a contiguous object in memory of a specific size. It is one object where you can place your data in and therefore you can only free/delete it as one object.
You are thinking that an array is a list of multiple objects, but that's not true. That would be true for something like a linked list, where you allocate individual objects and link them together.
You allocated one object of the type int[n] (one extent of memory for an array) using the operator new
int *p = new int[n];
Elements of the array were not allocated dynamically separately.
So to delete it you just need to write
delete []p;
If for example you allocated an array of pointers like
int **p = new int *[n];
and then for each pointer of the array you allocated an object of the type int like
for ( int i = 0;i < n;++i )
{
p[i] = new int( i );
}
then to delete all the allocated objects you need to write
for ( int i = 0; i < n; ++i )
{
delete p[i];
}
delete []p;
That is the number of calling of the operator delete or delete [] one to one corresponds to the number of calling operator new or new [].
One new always goes with one delete. Just as that.
In detail, when we request an array using new, what we actually do is to get a pointer that controls a contiguous & fixed block on the memory. Whatever we do with that array, we do it through that pointer and this pointer associates strictly with the array itself.
Furthermore, let's assume that you were able to delete an elemnent in the middle of that array. After the deletion, that array would fall apart and they are not contiguous anymore! By then, an array would not really be an array!
Because of that, we can not 'chop off' an array into separate pieces. We must always treat an array as one thing, not distinctive elements scattered around the memory.
Greatly simplyfyinh: in most systems memory is allocated in logical blocks which are described by the starting pointer of the allocated block.
So if you allocate an array:
int* array = new int[100];
OS stores the information of that allocation as a pair (simplifying) (block_begin, size) -> (value of array ptr, 100)
Thus when you deallocate the memory you don't need to specify how much memory you allocated i.e:
// you use
delete[] array; // won't go into detail why you do delete[] instead of delete - mostly it is due to C++ way of handling destruction of objects
// instead of
delete[100] array;
In fact in bare C you would do this with:
int* array = malloc(100 * sizeof(int))
[...]
free(array)
So in most OS'es it is not possible due to the way they are implemented.
However theoretically allocating large chunk of memory in fact allocate many smaller blocks which could be deallocated this way, but still it would deallocate smaller blocks at a time not one-by-one.
All of new or new[] and even C's malloc do exactly the same in respect to memory: requesting a fix block of memory from the operating system.
You cannot split up this block of memory and return it partially to the operating system, that's simply not supported, thus you cannot delete a single element from the array either. Only all or none…
If you need to remove an element from an array all you can do is copy the subsequent elements one position towards front, overwriting the element to delete and additionally remember how many elements actually are valid – the elements at the end of the array stay alive!
If these need to be destructed immediately you might call the destructor explicitly – and then assure that it isn't called again on an already destructed element when delete[]ing the array (otherwise undefined behaviour!) – ending in not calling new[] and delete[] at all but instead malloc, placement new for each element, std::launder any pointer to any element created that way and finally explicitly calling the constructor when needed.
Sounds like much of a hassle, doesn't it? Well, there's std::vector doing all this stuff for you! You should this one it instead…
Side note: You could get similar behaviour if you use an array of pointers; you then can – and need to – maintain (i.e. control its lifetime) each object individually. Further disadvantages are an additional level of pointer indirection whenever you access the array members and the array members indeed being scattered around the memory (though this can turn into an advantage if you need to move objects around your array and copying/moving objects is expensive – still you would to prefer a std::vector, of pointers this time, though; insertions, deletions and managing the pointer array itself, among others, get much safer and much less complicated).

Memory deallocation inside a member function

I was thinking about a this situation not for a real implementation but to understand better how pointers works.
class foo(){
foo();
~foo();
void doComplexThings(const std::vector<int*>& v){
int* copy;
for(int i = 0; i < v.size(); i++){
copy = v[i];
// do some stuffs
}
}
}
main(){
std::vector<int*> myVector; // suppose we have 100 elements
doComplexThings(myVector);
for(int i = 0; i < myVector.size(); i++){
delete myVector[i];
}
myVector.clear();
}
Ok, I know that have no sense to copy v[i] inside an other pointer, but I was thinking: copy do a memory leak?
After the execution of doComplexThings(), copy will continue to exist and will occupy space in the heap?
After deleting all elements it will continue to exist and point to a deallocated memory?
So logically if I do this things with complex objects I'll keep occupy the memory with unreference object? Or copy is saved in the stack because I don't use new? And at the end of doComplexThings it will be deleted?
I'm a bit confused, thanks!
There is some confusion on the topic of pointers in the C++ community. While it is true that smart pointers have been added to the library to alleviate problems with dynamic memory allocation, raw pointers are not obsolete. In fact, whenever you want to inspect another object without owning it, you should use a reference or raw pointer, depending on which suits your needs. If the concept of ownership is unclear to you, think of an object as being owned by another object if the latter is responsible for cleaning up afterwards (deleting the former).
For example most uses of new and delete should be replaces with the following (omitting std for brevity):
{
auto ptr_to_T = make_unique<T>(//constructor params);
do_stuff_with_smart_ptr(ptr_to_T);
do_stuff_with_T(*ptr_to_T);
do_stuff_with_raw_ptr(ptr_to_T.get());
} // automatic release of memory allocated with make_unique()
Notice how a function that takes a T* doesn't need a smart pointer if it doesn't keep a copy of the T* it is given, because it doesn't affect the lifetime of the object. The object is guaranteed to be alive past the return point of do_stuff_with_T() and its function signature signals that it doesn't own the object by taking a raw pointer.
On the other hand, if you need to pass the pointer to an object that is allowed to keep the pointer and reference it later, it is unclear when the object will need to be destroyed and most importantly by whom. This is solved via a shared pointer.
ClassThatNeedsSharedOwnership shared_owner;
{
auto ptr_to_T = make_shared<T>(//constructor params);
shared_owner.set_T(ptr_to_T);
// do a lot of stuff
}
// At this point ptr_to_T is destroyed, but shared_owner might keep the object alive
So how does the above factor in to your code. First of all, if the vector is supposed to own (keep alive) the ints it points to, it needs to hold unique_ptr<int> or shared_ptr<int>. If it is just pointing to ints held by something else, and they are guaranteed to be alive until after the vector is destroyed, you are fine with int*. In this case, it should be evident that a delete is never necessary, because by definition your vector and the function working on the vector are not responsible for cleaning-up!
Finally, you can make your code more readable by changing the loop to this (C++11 which you've tagged in the post):
for (auto copy : v){
// equivalent to your i-indexed loop with copy = v[i];
// as long as you don't need the value of i
do_stuff_to_int_ptr(copy);
// no delete, we don't own the pointee
}
Again this is only true if some other object holds the ints and releases them, or they are on the stack but guaranteed to be alive for the whole lifetime of vector<int*> that points to them.
No additional memory is allocated on the heap when you do this:
copy = v[i];
variable copy points to the same address as v[i], but no additional array is allocated, so there would be no memory leak.
A better way of dealing with the situation is to avoid raw pointers in favor of C++ smart pointers or containers:
std::vector<std::vector<int>> myVector;
Now you can remove the deletion loop, which is an incorrect way of doing it for arrays allocated with new int[length] - it should use delete[] instead:
delete[] myVector[i];
Basically you're illustrating the problem with C pointers which lead to the introduction of C++ unique and shared pointers. If you pass a vector of allocated pointers to an opaque member function, you've no way of knowing whether that function hangs onto them or not, so you don't know whether to delete the pointer. In fact in your example you don't seem to, "copy" goes out of scope.
The real answer is that you should only seldom use allocated pointers in C++ at all. The stl vector will serve as a safer, easier to use version of malloc / new. Then you should pass them about as const & to prevent functions from changing them. If you do need an allocated pointer, make one unique_ptr() and then you know that the unique_ptr() is the "owner" of the memory.

Pointers assigned inside an invoked function valid?

I want to understand whether in this piece of code, pointers stored in the vector by func() are valid when accessed from main_func(), and if so why?
void func(vector<double*>& avector) {
double a=0,b=0;
for (int i=0;i<10;i++) {
double *a = new double[2];
avector.push_back(a);
avector[avector.size()-1][0] = a;
avector[avector.size()-1][1] = b;
}
}
void main_func(){
vector<double*> v;
func(v);
for (int i=0;i<v.size();i++)
{
// access a
// References stored in vector valid???
}
}
Why don't you use a vector of pair vector<pair<double,double>>
http://www.cplusplus.com/reference/utility/pair/
Let's get to basics. A pointer is simply four-byte integer value denoting address in memory in which some data exists. Dynamic memory allocation is application-global, so if you allocate memory anywhere in your program by new, new[] or malloc (or something like this), you can use this memory anywhere you like and OS guarantees, that it won't be moved anywhere (in terms of address, that you got from the memory allocation routine).
So let's get back to your program. You allocate some memory inside the function and store the addresses of pointers to that memory in the vector. When you exit that function, these pointers are still completely valid and you can use them as you wish.
Don't forget to free them, when you don't need them anymore!
They are valid because you created them with new and that means they have dynamic storage duration. You do however lack the corresponding delete and therefore have a memory leak.
Your vector does not store references, but pointers to objects on the heap. That object is an array of two doubles, and you just copy the values from your local variable. So everything is alright (except that you don't release the memory).
If you somewhere (store and) return references or pointers to function locals, those won't have any meaning outside the function.

C++, vectors, pointers and objects confusion

I am working on a project as a homework for my university course of Systems Programming.
I got really confused with the matter of Pointers, Vectors, stacks and heaps.
Using C++.
I have to get a vector of objects which are courses, and those courses objects have several different fields.
What I did was this:
vector<CoursesObject> coursevector;
and then I created my Courses Object class, which contains the space left in course and name of course fields.
Now I want to add a new course, I do:
CoursesObject *theCourse = new CoursesObject(name, space);
now I want to add it to the handler vector:
coursevector.push_back(*theCourse);
With all I know, I created a vector of Courses objects on the stack, and made a new pointer to a new course that is on the heap, and added to the handler vector the pointer theCourse that points to the course object in the heap. Is what I said correct?
When I try to delete those course objects, I do:
for(int i=0; i<coursevector.size(); i++)
delete coursevector.at(i);
which gives me an error that it is not a pointer. But haven't I added to the coursevector a POINTER to the course object?
Please somebody explain, I have to handle the memory correctly and it seems that I am not getting it right.
This
vector<CoursesObject> coursevector;
is a vector of CourseObjects, so it cannot hold CourseObject pointers. When you do this:
coursevector.push_back(*theCourse);
you get a copy of the CoursesObject pointed at by theCourse stored in the vector. You do not need to delete any entries from the vector. In fact, you can't, because it doesn't hold pointers.
You program would be much simpler if you just avoided the dynamic allocation:
coursevector.push_back(CoursesObject(name, space));
You do not need to use new at all.
//This vector stores CoursesObject objects,
//not pointers to CoursesObjects.
vector<CoursesObject> coursevector;
//Construct theCourse with automatic storage
//duration.
CoursesObject theCourse(name, space);
//Copy theCourse into coursevector
coursevector.push_back(theCourse);
//theCourse will be automatically destroyed.
//coursevector (and all the objects that it contains)
//will be automatically destroyed.
all of your objects are not dynamically allocated, so you cannot delete them at any time during the program. Remember that you can only delete object once they are dynamically allocated:
int Var1 = 0; //cannot be deleted, scope and life will exist for the life of program
int * Var2 = new int; //CAN be deleted, dynamically allocated.
delete Var2; //free memory
You can however delete your last object, which is a pointer. I would grab the last element of the vector and call delete on it(which should be your pointer to the class).
when you do this:
coursevector.push_back(*theCourse);
actually you are dereferencing the pointer theCourse, so you are adding a copy of the object. You need to declare a vector of CourseObject pointers:
vector<CoursesObject *> coursevector;
Then you add an object:
coursevector.push_back(theCourse);
Now your code to delete the objects should work:
for(int i=0; i<coursevector.size(); i++)
delete coursevector.at(i);
coursevector can hold only CoursesObjects and not pointers to CoursesObjects, so you needn't use the new operator (check #Mankarse's answer). But, if you still want to hold pointers, then change the definition of coursevector to
vector<CoursesObject*> coursevector;
and push_back the value of the pointer as it is:
coursevector.push_back(theCourse);

C++ deleting a pointer to a pointer

So I have a pointer to an array of pointers. If I delete it like this:
delete [] PointerToPointers;
Will that delete all the pointed to pointers as well? If not, do I have to loop over all of the pointers and delete them as well, or is there an easier way to do it? My google-fu doesn't seem to give me any good answers to this question.
(And yeah, I know I need to use a vector. This is one of those "catch up on C++" type assignments in school.)
Yes you have to loop over the pointers, deleting individually.
Reason: What if other code had pointers to the objects in your array? The C++ compiler doesn't know if that's true or not, so you have to be explicit.
For an "easier way," two suggestions: (1) Make a subroutine for this purpose so at least you won't have to write the code more than once. (2) Use the "smart pointer" design paradigm where you hold an array of objects with reference-counters, then the objects are deleted when the objects are no longer referenced by any code.
I agree with Jason Cohen though we can be a bit clearer on the reason for needing to delete your pointers with the loop. For every "new" or dynamic memory allocation there needs to be a "delete" a memory de-allocation. Some times the "delete" can be hidden, as with smartpointers but it is still there.
int main()
{
int *pI = new int;
int *pArr = new int[10];
so far in the code we have allocated two chunks of dynamic memory. The first is just a general int the second is an array of ints.
delete pI;
delete [] pArr;
these delete statements clear the memory that was allocated by the "new"s
int ppArr = new int *[10];
for( int indx = 0; indx < 10; ++indx )
{
ppArr[indx] = new int;
}
This bit of code is doing both of the previous allocations. First we are creating space for our int in a dynamic array. We then need to loop through and allocate an int for each spot in the array.
for( int indx = 0; indx < 10; ++indx )
{
delete ppArr[indx];
}
delete [] ppArr;
Note the order that I allocated this memory and then that I de-allocated it in the reverse order. This is because if we were to do the delete [] ppArr; first we would lose the array that tells us what our other pointers are. That chunk or memory would be given back to the system and so can no longer be reliably read.
int a=0;
int b=1;
int c=2;
ppArr = new int *[3];
ppArr[0] = &a;
ppArr[1] = &b;
ppArr[2] = &c;
This I think should be mentioned as well. Just because you are working with pointers does not mean that the memory those pointers point to was dynamically allocated. That is to say just because you have a pointer doesn't mean it necessarily needs to be delete. The array I created here is dynamically allocated but the pointers point to local instances of ints When we delete this we only need to delete the array.
delete [] ppArr;
return 0;
}
In the end dynamically allocated memory can be tricky and anyway you can wrap it up safely like in a smart pointer or by using stl containers rather then your own can make your life much more pleasant.
See boost pointer container for a container that does the automatic deletion of contained pointers for you, while maintaining a syntax very close to ordinary STL containers.
Pointers are pretty much just memory references and not spiffy little self-cleaning .net objects. Creating proper destructors for each class will make the deletion a little cleaner than massive loops throughout the code.
Let's take a (pseudocoded) real world example .Imagine that you had a class like this:
class Street
{
public:
Street();
~Street();
private:
int HouseNumbers_[];
}
typedef *Street StreetSign;
If you have an array of street signs, and you delete your array of streetsigns, that doesn't mean that you automatically delete the sreets. They re still there, bricks and mortar, they just don't have those signs pointing to them any more. You have got rid of those specific instances of pointers to the streets.
An array of pointers is (conceptually) a bit like an array of integers, it's an array of numbers representing the memory locations of various objects. It isn't the objects themselves.
If you delete[] the array of pointers, all you have done is delete an array of integers.
I think you're going to have to loop over I'm afraid.
I don't know why this was answered so confusingly long.
If you delete the array of pointers, you will free
the memory used for an array of usually ints.
a pointer to an object is an integer containing the adress.
You deleted a bunch of adresses, but no objects.
delete does not care about the content of a memory space,
it calls a destructor(s) and marks the mem as free.
It does not care that it just deleted a bunch of adresses
of objects, it merely sees ints.
That's why you have to cycle through the array first! and call delete
on every element, then you can delete the storage of the array itself.
Well, now my answer got somewhat long... .... strange... ;)
Edit:
Jason's answer is not wrong, it just fails to hit the spot. Neither
the compiler nor anything else in c(++) cares about you deleting stuff that is elsewhere
pointed to. You can just do it. Other program parts trying to use the deleted objects
will segfault on you. But no one will hinder you.
Neither will it be a problem to destroy an array of pointers to objects, when the objects
are referenced elsewhere.