C++ Containers of pointers - c++

I have been pondering an issue today and it's difficult to find the answer on google.
I'm trying to understand the STL container behaviour when dealing with pointers to both objects allocated on the heap, and on the stack.
So, start with objects, no pointers ... imagine I have ...
std::vector<int> myVec;
while(true)
{
int myInt = 5;
myVec.push_back(myInt);
myVec.pop_back();
}
My understanding is that the pop_back() method will ensure the integers contained in the vector are deleted, not just removed from the container. So if this ran and did a billion iterations, I should not expect to leak memory. Everything I insert, will be deleted. A memory check shows this behaviour.
Now consider I use a vector of pointers (to objects on the heap) ...
std::vector<int*> myVec;
while(true)
{
int * myIntP = new int(5);
myVec.push_back(myIntP);
myVec.pop_back();
}
In this case, only the pointer itself ought to be removed each time pop_back() is called, and the underlying object remains un-deleted, causing a memory leak. So after a billion iterations I have quite some significant memory being used, even though I have no entries in my vector.
Now what if I have a vector of pointers (to objects on the stack) ...
std::vector<int*> myVec;
while(true)
{
int myInt = 5;
int * myIntP = &myInt;
myVec.push_back(myIntP);
myVec.pop_back();
}
Here the pointers point to stack objects. Is their memory freed in the call to pop_back(), or not? A memory check showed me that this behaviour was no memory leaked. The small amount of memory used, indicated that this behaved like objects on the stack. However this was not expected to me, because if the pointer had been passed into me from another function, to a stack variable i.e.
void myFunc(int * myIntP)
{
std::vector<int*> myVec;
myVec.push_back(myIntP);
myVec.pop_back();
}
int main()
{
int myInt = 5;
int * myIntP = &myInt;
myFunc(myIntP);
std::cout << (*myIntP) << std::endl;
return 0;
}
Then allowing the vector to free this memory, would render my myIntP pointing to removed data. So surely this can't be correct?
Could anyone help explain?
Also is there a name for "a pointer pointing to a variable on the stack" i.e. not initialised with "new"?
Thanks
Joey

while(true)
{
int myInt = 5;
int * myIntP = &myInt;
myVec.push_back(myIntP);
myVec.pop_back();
}
You only actually have one int here, myInt with a value of 5. The loop will re-use the same one. You push a pointer to that one int into the vector and then remove it. Nothing else is happening. There isn't a memory leak because you are not allocating new ints.
STD containers do nothing different for pointers than they would for a 32/64 bit interger. As far as they care, a pointer is just another number. So, if you insert a pointer into a container, it is your responsibility to delete it.

If you make a pointer to a variable on the stack, the variable will be destructed when it goes out of scope, regardless of the pointer. And destructing the pointer (as long as you don't call delete on it) will have no effect on the variable.
So if you stop using your pointer before, no problem, if you store it longer, problem...
And if you plan on using pointers on dynamically allocated variable, you should look into smart pointers.

Here the pointers point to stack objects. Is their memory freed in the call to pop_back(), or not?
No, they are not. They are freed when they go out of scope, which happens at the }. After the }, the memory is no longer used for this variable (the stack-frame popped off) and will be reused! So if you didn't pop-off the pointer right after pushing it, your vector would contain a dangling pointer when the variable goes out of scope.

So, let's go through each of your examples:
std::vector<int> myVec;
while(true)
{
int myInt = 5;
myVec.push_back(myInt);
myVec.pop_back();
}
The push_back() method makes a copy of the argument and stores the copy internally. So, if you were storing an stack-allocated object instead of a primitive, a copy constructor would have been called. The pop_back() method does not assume anything either. It removes the copy of the item you stored (whether it was a value or a pointer) and removes it from its internal storage. If the copy stored was a stack-allocated object, the class' destructor will be called when the container manages its internal memory because the copy item will no longer be in scope.
Your second example:
std::vector<int*> myVec;
while(true)
{
int * myIntP = new int(5);
myVec.push_back(myIntP);
myVec.pop_back();
}
As you stated, the integer is allocated on the heap. Calling push_back() still stores the argument. In this case, you are not storing the value of the integer "5", the value of the pointer, an address of a memory location that contains the value of "5". Since you allocated the memory that stores the "5", you are responsible for getting that pointer and deallocate the memory. The pop_back() method does not delete the pointer for you nor returns you a copy of the pointer.
Your third example has subtle differences:
std::vector<int*> myVec;
while(true)
{
int myInt = 5;
int * myIntP = &myInt;
myVec.push_back(myIntP);
myVec.pop_back();
}
In this case, you are not allocating any memory on the heap. You assigning the address of myInt, which is a stack-allocated value, to a pointer. Stack memory lives through out the life of a process and does not deallocate on its own. However, once you leave the current scope (the while loop), the memory reused by something else. The memory is still there, but it may no longer have the value you expect.
Your last example:
void myFunc(int * myIntP)
{
std::vector<int*> myVec;
myVec.push_back(myIntP);
myVec.pop_back();
}
int main()
{
int myInt = 5;
int * myIntP = &myInt;
myFunc(myIntP);
std::cout << (*myIntP) << std::endl;
return 0;
}
You were expected the memory for myInt to be dealloated after making myFunc() was called. However, container methods do not modify the supplied values. They copy them. When myFunc() pushed the myIntP pointer, it is pushing the pointer, the address of what myIntP points to, not the value in memory of that address. You would have to dereference the pointer, using call:
myVec.push_back(*myIntP);
Note that even if you did this, containers copy the value. So, myInt is still unaffected.

You are confusing and conflating "destruction" and "deletion" -- they are NOT the same thing, but are two different concepts in C++.
Deletion can only happen with pointers -- if you try to delete a non-pointer, you'll get a compile-time error. Deletion first destroys the pointed at object and then returns the memory for it to the heap.
Destruction on the other hand can happen with anything, but is mostly only of interest with classes, where it calls the destructor. With any type that has no destructor (such as int or any raw pointer type), destruction does nothing. While you CAN destroy an object manually, you pretty much never do -- it happens automatically for you when something else happens. For example, when a local variable goes out of scope, it is destroyed.
So in your code above, what happens? Well you have a local std::vector which is destroyed when it goes out of scope. Its destructor will delete anything it allocated internally, and destroy all the elements of the vector. It will NOT however, delete any elements of the vector. When you have vector<int>, that's all there is, since nothing else was allocated, but when you have a vector<int *>, if those pointers were allocated, they'll leak. If they weren't allocated (if they point at locals), there's nothing to leak.

I think you need to learn deep the scope variable validity
exemple :
{
int myVar;//Construct myVar on the stack
}//At this point, myVar is deleted with the stack
in your last exemple, you declare myInt at the start of main and don't do anything on value in myFunc.
It's normal to don't lose myInt data. it will be erase after the return 0;

Related

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.

double free or corruption when using object instead of pointer

Why does the first code snippet result in a double free or corruption error when calling the destructor, while the second snippet works fine?
int main( int argc, char** argv )
{
vector<int> vec = *new vector<int>(10);
vec.at(3) = 6;
vec.~vector();
}
This one works:
int main( int argc, char** argv )
{
vector<int> *vec = new vector<int>(10);
vec->at(3) = 6;
vec->~vector();
}
And even if the destructor is called two times: Why does the error appear in the second last line(according to gbd) and not at } when the object passes out of scope?
Let's examine the code line by line. Program one:
vector<int> vec = *new vector<int>(10);
A vector vec is defined left of the =. Another, unnamed vector is created right of the = on the heap. Note that this involves two free store allocations: One for the (small) vector object proper, and a second one for the data in it, 10 ints. The address returned by new is not preserved anywhere, but is dereferenced immediately so that the expression to the right of = is a vector object. It is used to copy-initialize vec. This involves allocating memory for vec's data on the free store and copying all of the anonymous vector's elements into it. Note that vec's data is in a different location from the right hand side vector's data.
vec.at(3) = 6;: Irrelevant for the discussion.
vec.~vector();: Executing vec's destructor will free the memory allocated for data on the free store when vec was initialized. It will not attempt to free vec's memory (which is good because vec is not on the heap but on the stack and will be destroyed automatically when the stack is unwound because the scope is left).
}: The scope of vec ends so that vec's destructor is called again (the language does not keep book of destruction, for example there is no "destroyed" flag in objects). This is a bad thing because, as we know, ~vector() tries to free the memory allocated for its data. (It's debatable whether it should also set the data pointer to null in which case multiple de-allocation attempts would not be catastrophic. The counter argument is that that would only mask catastrophic programming errors.)
Apart from the obvious double de-allocation of vec's data due to the erroneous explicit destructor call it's also important that the vector on the free store which was used for vec's initialization is never freed nor destroyed. (It cannot be freed since the address is lost.) That is ok for vectors of PODs in a fully-featured runtime environment: The POD elements do not need destruction, and the runtime returns a process's heap to the OS when the process exits. But the hints are obvious: What if the elements require destruction (think database connections which now are never closed); and there are standalone implementations where the memory may not be returned to the OS (which OS?), or the code gets used as part of a long-running server without reconsideration.
Program two:
std::vector<int> *vec = new std::vector<int>(10);
This line defines a pointer vec on the left side of =. The right side creates a vector of ints on the free store. The address of that unnamed vector is used to initialize the pointer vec. Note that, as in the first example, two allocations on the free store are involved in the call to new: The (small) memory for the vector proper, and the (separate, large) memory for the data the vector "contains".
vec->at(3) = 6; is irrelevant to the discussion.
vec->~vector(); explicitly calls vec's destructor. This frees the vector's data but leaves the vector proper untouched. The latter is bad because the vector object to which vec points was allocated on the free store and should be freed as well. The proper way to do both at the same time is calling delete as suggested by another answer. (But the discussion above applies -- in a normal runtime it doesn't matter for an int vector if the program ends anyway).
}: The scope of the pointer vec ends, which doesn't trigger anything (in particular, it doesn't free the memory vec points to, which is bad here, and it doesn't call the vector's destructor, which is good here). Note that smart pointers would behave differently and potentialy call delete on the raw pointers they hold internally when their scope ends.
This vector<int> vec = *new vector<int>(10); actually creates two vectors. The first one is created by new vector<int>(10). Then a second one, vec, is created using the copy constructor.
The first one is never destroyed. The second is destroyed twice, by manually calling the destructor and automatically when it falls out of scope.
First case:
vector<int> vec = *new vector<int>(10);
Here three things happen:
You dynamically allocate a vector. new returns a pointer. In this case it is a temporary variable, which does not have a name.
You dereference this pointer and get an rvalue.
You construct another object, vec, initialising it with the rvalue from the previous step. This effectively calls a copy-constructor vector(const vector&).
As a result, there are two vectors. The first one is somewhere in the heap, and you do not have a pointer to it. This is a memory leak. Then, there is an automatic duration object vec. Both vectors have equal content.
vec.~vector();
Here you explicitly call a descructor of an automatic duration object. You almost never need to do it. This is mainly intended to be used for implementing placement new.
As soon as you leave the scope (e.g. leave the function body), the destructor is automatically called once more. Hence, you get a double-free error.
Second case:
vector<int> *vec = new vector<int>(10);
vec->~vector();
Here you destroy the object (i.e. call the destructor), but do not free the memory it occupied. Thus, you still have a memory leak. But, as dynamic objects are not automatically destroyed when we leave the scope, no double-free errors occur.
You should use delete vec; to destroy the dynamically allocated vector. It will call the destructor and free the memory.
Both versions contain errors but the first is really bad here is how it should look if you decide to use a vector object:
int main()
{
std::vector<int> vec(10);
vec.at(3) = 6;
}
And this is how it could look using the pointer:
int main( int argc, char** argv )
{
std::vector<int> *vec = new std::vector<int>(10);
vec->at(3) = 6;
delete vec;
}
last line is not even necessary as the program will terminate and ram will be free in anycase.

Do functions clear dynamic memory upon exiting scope?

In C++, how does a function treat memory that has been dynamically allocated upon exiting the scope of the function? Is this memory cleared, or can it be passed back into the main block?
In context: I have a function, and I pass it a pointer to double to serve as an array. I dynamically allocate this memory within the function, initialise the elements and the exit the function.
void my_func(double* ptr){
ptr = new double[2];
ptr[0] = 15; ptr[1] = 10;
}
In the main block, I then use the newly allocated array.
int main(){
double* ptr;
my_func(ptr);
cout << ptr[0] + ptr[1] << endl;
delete[] ptr;
return 0;
Will this work? Are there dangers/pitfalls associated with this approach?
In C++, how does a function treat memory that has been dynamically allocated upon exiting the scope of the function? Is this memory cleared, or can it be passed back into the main block?
In C++, memory that has been manually (dynamically) allocated has to be manually deallocated.
In context: I have a function, and I pass it a pointer to double to serve as an array. I dynamically allocate this memory within the function, initialise the elements and the exit the function.
You are taking the pointer by value, so while you can change the contents of what the pointer points to you cannot change the pointer itself. Doing so changes only the local copy of the pointer. If you take the pointer by reference, then it would work:
void my_func(double*& ptr)
{
ptr = new double[2];
ptr[0] = 15; ptr[1] = 10;
}
Will this work? Are there dangers/pitfalls associated with this approach?
It will mostly work, but its not the way to go in C++ because of the associated pitfalls. Better go with a vector:
std::vector<int> my_func()
{
std::vector<int> buffer;
buffer.push_back(15);
buffer.push_back(10);
return buffer;
}
Will this work? Are there dangers/pitfalls associated with this approach?
It may work as long as nothing goes wrong. If an exception gets thrown, it'll generally leak memory. To avoid that, you generally want to free the memory in the destructor of some class, then create an instance of that class with automatic storage duration. That means it'll be destroyed when it goes out of scope, and will (in turn) release the memory it's controlling.
The standard library already has a variety of containers to do that. What you have is closest to a std::vector, but there are also std::deque, std::list etc.

std::vector Destruction and Unexpected Memory Leak

Consider the following example:
#include <vector>
class Foo {
std::vector<int*> v;
public:
Foo() {
this->v.push_back(new int(23));
this->v.push_back(new int(24));
this->v.push_back(new int(25));
}
~Foo() {
}
};
int main() {
Foo f;
return 0;
}
When f goes out of scope in main(), f's destructor is called, which should indirectly free f.v. According to this, the destructor of each element of the vector v should now be called.
However, when I run this program in valgrind, I find that the int*'s were not deallocated.
$ valgrind --leak-check=full ./a.out
What am I missing here?
std::vector<T> does indeed call the destructor of T when it is destroyed. Here T is int *. The destructor of int * does nothing. The storage for the int * itself is freed, but the ints they point to are not.
Consider:
int main() {
int *x = new int(23);
return 0;
}
This exhibits the same problem; when x goes out of scope, its destructor is indeed called, and the storage for the pointer that is x is freed, but since the destructor of a pointer is a no-op, the pointed-to int is not freed.
More to the point, vector doesn't know how the ints were allocated. They might be allocated by new int, but they could also point to elements inside an array allocated with new int[200], or they might point to malloc'd data, or they might point into a mmap'd buffer, or they might point to struct elements, or two vectors might be pointing to the same ints... etc. vector isn't smart enough to divine what you want done with these, and so it leaves them alone (additionally, giving vector logic to delete pointed-to elements would break vectors of non-pointer elements such as std::vector<int>, as you can't delete an int!)
You need to either use a std::vector<int>, or use a smart pointer in conjunction with it, eg std::vector<boost::shared_ptr<int> >. Note that using smart pointers may add overhead; with C++0x you should be able to use std::vector<std::unique_ptr<int>> in conjunction with std::move to avoid this overhead. Boost also has pointer vectors that free the pointed-to elements as you expected as well.
The destructor of each element of the vector v should now be called
Yes: the int* objects stored in the vector are destroyed (which is effectively a no-op). The objects pointed to by the pointers in the container are not destroyed.
Consider the following, equally valid program:
{
int x;
std::vector<int*> v;
v.push_back(&x);
} // x cannot be delete'd because it isn't dynamically allocated.
You should use a smart pointer, like std::unique_ptr or shared_ptr so that you don't have to worry about the memory management (do not use std::auto_ptr; it is incompatible with the Standard Library containers because it isn't really copyable). If you don't use a smart pointer then you need to destroy the dynamically objects yourself; doing this correctly is rather difficult.
Each element of your vector is an int *. When an int * is destroyed, the language does not automatically call delete on it. In other words, it's the pointer being destroyed, not the pointee.
Since you are using the new keyword, the integers are being allocated on the heap rather than the stack. In other words, they are being allocated dynamically. In other words, you need to clean up after it.
The "destructor" for a pointer type is to simply delete that pointer. It does not touch the data which is located at the memory address stored by the pointer. Consider the following example:
int a = 5;
int* i = &a;
if (true)
{
int* j = i;
} //j goes out of scope, should *i and a be deleted? no.
So you will need to do this in the destructor:
std::vector<int*>::iterator iter;
for (iter = v.begin(); iter != v.end(); iter++)
{
delete *iter;
}

C++ Memory allocation question involving vectors

vector< int > vect;
int *int_ptr = new int(10);
vect.push_back( *int_ptr );
I under stand that every "new" needs to be followed by a "delete" at some point but does the clear() method clean this memory?
What about this method of doing the same thing:
vector< int > vect;
int int_var = 10;
vect.push_back( int_var );
From what I understand, clear() calls the variables destructors, but both vect.push_back() methods in this example push an object on the vector, not a pointer. so does the first example using an int pointer need something other than clear() to clean up memory?
The first method leaks because the vector never takes ownership of the allocated pointer. In fact, it doesn't contain a pointer at all, only a copy of the value.
The second method does not leak, as no memory is dynamically allocated (except internally in the vector -- it will handle that memory itself).
When you push_back on a vector, you add a copy of the data to the vector. Therefore, in both cases, the original data still needs to be freed. In the first case, you need to delete it; in the second, it will be "freed" by the stack pointer as it goes out of scope.
Vectors make copies on push_back. Since a pointer is 'just another variable' (but one that happens to point to memory), when you push_back an integer pointer that has been previously allocated, you copy the pointer's value into the vector, causing a potential dangling pointer, since there will be two pointers pointing at the same spot in memory.
In your first example, you would need to delete the memory manually. One strategy I've used in the past for meddling with graph classes is to have something like this (vast amounts of stuff redacted due to being at work and typing quickly):
class graph //quick-format
{
vector<node*> nodes;
add_node(node n)
{
node *temp = new node;
*temp = n;
nodes.push_back(temp)
}
~graph()
{
for(int i = 0; i < nodes.size(); i++)
delete nodes[i];
}
};
As a caveat, graph's copy semantics will have to be examined. As it stands, it will result in deleting previously-free'd memory. The advantage is that you can always have the same set of nodes hanging around. Caveat Emptor, like any direct memory usage..
However, if you simply push a non-pointer variable, there is no possibility of memory leaking from your end. Possibly the vector will leak, but... that is practically impossible at this point in the maturity of the tools.