Pointers to objects in function scope - c++

When you create some pointers inside the scope of a function, what happens when the function goes out of scope? Do they get destroyed or should I call delete on them at some point?
void XMLDocument::AddNode(XMLNode& node)
{
std::string val = node.GetNodeName();
TiXmlElement* el = new TiXmlElement(val.c_str()); // What about this object ptr?
TiXmlText * txt = new TiXmlText(node.GetNodeValue().c_str()); // And this one?
el->LinkEndChild(txt);
document.LinkEndChild(el);
}

Normally, you need to call delete on both the pointers in order to avoid memory leaks. But in you case, it looks like you are putting this pointer in a document object (I am assuming document stores the pointer itself and will not create copy of the pointed to object itself). So if you call delete here, the pointer you have given to the document object will be invalid one. So if document object takes ownership of deleting the memory you allocated in this function, then you should not call delete here, else if it is creating the copy of the object you passed, then you need to delete it here. Using a smart pointer will be quite useful in these type of scenarios. Take a look at boost::shared_ptr for more details.

The only thing that can be stated for sure is that immediately after the exit of this function, neither of those pointers has been returned to the heap.
What happens after the function exits depends on the contract for memory usage that is implied by passing a pointer into LinkEndChild. Do you still own the memory after this, or does it get cleaned up when the new parent (in this case document, which accesses the memory directly for el, and via el for txt) is cleaned up? If the former, then you are correct not to delete it. If the latter, then at some point you need to clean it up, presumably after document (global? class member?) is done with.
A further nuance is what is the contract on construction of TiXmlElement and TiXmlText - do they copy the input C-string, or use them by reference?
I would guess that it's XmlDocument's doc to clean up all memory that is linked into the document. Kind of messy, though. Check the destructor XmlDocument::~XlmDocument, see if it walks a list of children cleaning them up (recursively).
EDIT: This looks like TinyXML, in which case it's supposed to clean up all the memory you give it on destruction. See here for a discussion : http://www.gamedev.net/community/forums/topic.asp?topic_id=518023
The semantics of TinyXML clearly imply
that (a) it owns the document tree,
and (b) you pass in nodes that you
allocate. I can see no good argument
for it not simply using the delete
operator on everything linked into it.
EDIT: In fact, given that TinyXML (or
at least the copy I have here) clearly
has while ( node ) { temp = node; node
= node->next; delete temp; } in the TiXMLNode destructor, I'm guessing
this is just a bug in the TinyXML++
wrapper.
See also previous Stack Overflow question about TinyXml memory management here.
The documentation for LinkEndChild
says this:
NOTE: the node to be added is passed
by pointer, and will be henceforth
owned (and deleted) by tinyXml. This
method is efficient and avoids an
extra copy, but should be used with
care as it uses a different memory
model than the other insert functions.

When you use new, memory from the heap is allocated, while the objects locally declared in a function are allocated on the stack.
The objects allocated to the stack stop to exist after the method call.
In your case TiXmlElement* el is a pointer allocated on the stack that references memory on the heap. Once you leave the function, the el pointer will stop to exist (since it was on the stack) but the memory that it referenced, still exists (was on the heap). So if that memory is not "freed", it is considered as "leaked"

Related

Can i delete a statically defined variable using delete operator? [duplicate]

I have an object with a vector of pointers to other objects in it, something like this:
class Object {
...
vector<Object*> objlist;
...
};
Now, Objects will be added to list in both of these ways:
Object obj;
obj.objlist.push_back(new Object);
and
Object name;
Object* anon = &name;
obj.objlist.push_back(anon);
If a make a destructor that is simply
~Object {
for (int i = 0; i < objlist.size(); i++) {
delete objlist[i];
objlist[i] = NULL;
}
}
Will there be any adverse consequences in terms of when it tries to delete an object that was not created with new?
Yes, there will be adverse effects.
You must not delete an object that was not allocated with new. If the object was allocated on the stack, your compiler has already generated a call to its destructor at the end of its scope. This means you will call the destructor twice, with potentially very bad effects.
Besides calling the destructor twice, you will also attempt to deallocate a memory block that was never allocated. The new operator presumably puts the objects on the heap; delete expects to find the object in the same region the new operator puts them. However, your object that was not allocated with new lives on the stack. This will very probably crash your program (if it does not already crash after calling the destructor a second time).
You'll also get in deep trouble if your Object on the heap lives longer than your Object on the stack: you'll get a dangling reference to somewhere on the stack, and you'll get incorrect results/crash the next time you access it.
The general rule I see is that stuff that live on the stack can reference stuff that lives on the heap, but stuff on the heap should not reference stuff on the stack because of the very high chances that they'll outlive stack objects. And pointers to both should not be mixed together.
No, you can only delete what you newed
Object* anon = &name;
When name goes out of scope, you will have an invalid pointer in your vector.
What you're actually asking is whether it's safe to delete an object not allocated via new through the delete operator, and if so, why?
Unfortunately, this is obfuscated by some other problems in your code. As mentioned, when name goes out of scope, you're going to end up with an invalid pointer.
See zneak's answer for why your original question doesn't result in a safe operation, and why the scope for name actually matters.
This will not work - if you delete an object that wasn't allocated by new you've violated the rules or the delete operator.
If you need to have your vector store objects that may or may not need to be deleted, you'll need to keep track of that somehow. One option is to use a smart pointer that keeps track of whether the pointed to object is dynamic or not. For example, shared_ptr<> allows you to specify a deallocator object when constructing the shard_ptr<> and as the docs mention:
For example, a "no-op" deallocator is useful when returning a shared_ptr to a statically allocated object
However, you should still be careful when passing pointers to automatic variables - if the vector's lifetime is longer than the lifetime of the variable then it'll be refering to garbage at some point.

Memory leak issue; deleting a pointer

If I have a pointer pointing to a specific memory address at the heap. I would like this same pointer to point to another memory address, should I first delete the pointer? But, in this case am I actually deleting the pointer or just breaking the reference (memory address) the pointer is pointing at?
So, in other words, if I delete a pointer, does this mean it doesn't exist any more? Or, it is there, but not pointing to where it was?
The syntax of delete is a bit misleading. When you write
T* ptr = /* ... */
delete ptr;
You are not deleting the variable ptr. Instead, you are deleting the object that ptr points at. The value of ptr is unchanged and it still points where it used to, so you should be sure not to dereference it without first reassigning it.
There is no requirement that you delete a pointer before you reassign it. However, you should ensure that if you are about to reassign a pointer in a way that causes you to lose your last reference to the object being pointed at (for example, if this pointer is the only pointer in the program to its pointee), then you should delete it to ensure that you don't leak memory.
One technique many C++ programmers use to simplify the logic for when to free memory is to use smart pointers, objects that overload the operators necessary to mimic a pointer and that have custom code that executes automatically to help keep track of resources. The new C++0x standard, for example, will provide a shared_ptr and unique_ptr type for this purpose. shared_ptr acts like a regular pointer, except that it keeps track of how many shared_ptrs there are to a resource. When the last shared_ptr to a resource changes where it's pointing (either by being reassigned or by being destroyed), it then frees the resource. For example:
{
shared_ptr<int> myPtr(new int);
*myPtr = 137;
{
shared_ptr<int> myOtherPtr = myPtr;
*myPtr = 42;
}
}
Notice that nowhere in this code is there a call to delete to match the call to new! This is because the shared_ptr is smart enough to notice when the last pointer stops pointing to the resource.
There are a few idiosyncrasies to be aware of when using smart pointers, but they're well worth the time investment to learn about. You can write much cleaner code once you understand how they work.
When you delete a pointer you release the memory allocated to the pointed to object. So if you just want your pointer to point to a new memory location you should not delete the pointer. But if you want to destroy the object currently it is pointing to and then then point to a different object then you should delete the pointer.
xtofl, while being funny, is a bit correct.
If YOU 'new' a memory address, then you should delete it, otherwise leave it alone. Maybe you are thinking too much about it, but you think about it like this. Yea, the memory is always there, but if you put a fence around it, you need to take the fence down, or no one else can you it.
When you call delete you mark the memory pointed to by the pointer as free - the heap takes ownership of it and can reuse it, that's all, the pointer itself is usually unchanged.
What to do with the pointer depends on what you want. If you no longer need that memory block - use delete to free the block. If you need it later - store the address somewhere where you can retrieve it later.
To answer your question directly, this has been asked before. delete will delete what your pointer points to, but there was a suggestion by Bjarne Stroustrup that the value of the pointer itself can no longer be relied upon, particularly if it is an l-value. However that does not affect the ability to reassign it so this would be valid:
for( p = first; p != last; ++p )
{
delete p;
}
if you are iterating over an array of pointers, all of which had been allocated with new.
Memory management in C++ is best done with a technique called RAII, "resource acquisition is initialization".
What that actually means is that at the time you allocate the resource you immediately take care of its lifetime, i.e. you "manage" it by putting it inside some object that will delete it for you when it's no longer required.
shared_ptr is a technique commonly used where the resource will be used in many places and you do not know for certain which will be the last one to "release" it, i.e. no longer require it.
shared_ptr is often used in other places simply for its semantics, i.e. you can copy and assign them easily enough.
There are other memory management smart pointers, in particular std::auto_ptr which will be superceded by unique_ptr, and there is also scoped_ptr. weak_ptr is a methodology to be able to obtain a shared_ptr if one exists somewhere, but not holding a reference yourself. You call "lock()" which gives you a shared_ptr to memory or a NULL one if all the current shared pointers have gone.
For arrays, you would not normally use a smart pointer but simply use vector.
For strings you would normally use the string class rather than think of it as a vector of char.
In short, you do not "delete a pointer", you delete whatever the pointer points to.
This is a classical problem: If you delete it, and someone else is pointing to it, they will read garbage (and most likely crash your application). On the other hand, if you do not and this was the last pointer, your application will leak memory.
In addition, a pointer may point to thing that were not originally allocated by "new", e.g. a static variable, an object on the stack, or into the middle of another object. In all those cases you're not allowed to delete whatever the pointer points to.
Typically, when designing an application, you (yes, you) have to decide which part of the application owns a specific object. It, and only it, should delete the objects when it is done with it.

Is it possible to delete a non-new object?

I have an object with a vector of pointers to other objects in it, something like this:
class Object {
...
vector<Object*> objlist;
...
};
Now, Objects will be added to list in both of these ways:
Object obj;
obj.objlist.push_back(new Object);
and
Object name;
Object* anon = &name;
obj.objlist.push_back(anon);
If a make a destructor that is simply
~Object {
for (int i = 0; i < objlist.size(); i++) {
delete objlist[i];
objlist[i] = NULL;
}
}
Will there be any adverse consequences in terms of when it tries to delete an object that was not created with new?
Yes, there will be adverse effects.
You must not delete an object that was not allocated with new. If the object was allocated on the stack, your compiler has already generated a call to its destructor at the end of its scope. This means you will call the destructor twice, with potentially very bad effects.
Besides calling the destructor twice, you will also attempt to deallocate a memory block that was never allocated. The new operator presumably puts the objects on the heap; delete expects to find the object in the same region the new operator puts them. However, your object that was not allocated with new lives on the stack. This will very probably crash your program (if it does not already crash after calling the destructor a second time).
You'll also get in deep trouble if your Object on the heap lives longer than your Object on the stack: you'll get a dangling reference to somewhere on the stack, and you'll get incorrect results/crash the next time you access it.
The general rule I see is that stuff that live on the stack can reference stuff that lives on the heap, but stuff on the heap should not reference stuff on the stack because of the very high chances that they'll outlive stack objects. And pointers to both should not be mixed together.
No, you can only delete what you newed
Object* anon = &name;
When name goes out of scope, you will have an invalid pointer in your vector.
What you're actually asking is whether it's safe to delete an object not allocated via new through the delete operator, and if so, why?
Unfortunately, this is obfuscated by some other problems in your code. As mentioned, when name goes out of scope, you're going to end up with an invalid pointer.
See zneak's answer for why your original question doesn't result in a safe operation, and why the scope for name actually matters.
This will not work - if you delete an object that wasn't allocated by new you've violated the rules or the delete operator.
If you need to have your vector store objects that may or may not need to be deleted, you'll need to keep track of that somehow. One option is to use a smart pointer that keeps track of whether the pointed to object is dynamic or not. For example, shared_ptr<> allows you to specify a deallocator object when constructing the shard_ptr<> and as the docs mention:
For example, a "no-op" deallocator is useful when returning a shared_ptr to a statically allocated object
However, you should still be careful when passing pointers to automatic variables - if the vector's lifetime is longer than the lifetime of the variable then it'll be refering to garbage at some point.

How to safely delete multiple pointers

I have got some code which uses a lot of pointers pointing to the same address.
Given a equivalent simple example:
int *p = new int(1);
int *q = p;
int *r = q;
delete r; r = NULL; // ok
// delete q; q = NULL; // NOT ok
// delete p; p = NULL; // NOT ok
How to safely delete it without multiple delete?
This is especially difficult if I have a lot of objects which having pointers all pointing to the same address.
Your tool is shared_ptr of the boost library. Take a look at the documentation: http://www.boost.org/doc/libs/1_44_0/libs/smart_ptr/shared_ptr.htm
Example:
void func() {
boost::shared_ptr<int> p(new int(10));
boost::shared_ptr<int> q(p);
boost::shared_ptr<int> r(q);
// will be destructed correctly when they go out of scope.
}
The answer, without resorting to managed pointers, is that you should know whether or not to delete a pointer based on where it was allocated.
Your example is kind of contrived, but in a real world application, the object responsible for allocating memory would be responsible for destroying it. Methods and functions which receive already initialized pointers and store them for a time do not delete those pointers; that responsibility lies with whatever object originally allocated the memory.
Just remember that your calls to new should be balanced by your calls to delete. Every time you allocate memory, you know you have to write balancing code (often a destructor) to deallocate that memory.
The "modern" answer is to use a smart pointer and don't do any manual deletes.
boost::shared_ptr<int> p(new int(1));
boost::shared_ptr<int> q = p;
boost::shared_ptr<int> r = q;
End of story!
The problem you are facing is that the ownership semantics in your program are not clear. From a design point of view, try to determine who is the owner of the objects at each step. In many cases that will imply that whoever creates the object will have to delete it later on, but in other cases ownership can be transferred or even shared.
Once you know who owns the memory, then go back to code and implement it. If an object is the sole responsible for a different object, the it should hold it through a single-ownership smart pointer (std::auto_ptr/unique_ptr) or even a raw pointer (try to avoid this as it is a common source of errors) and manage the memory manually. Then pass references or pointers to other objects. When ownership is transfered use the smart pointer facilities to yield the object to the new owner. If the ownership is truly shared (there is no clear owner of the allocated object) then you can use shared_ptr and let the smart pointer deal with the memory management).
Why are you trying to delete pointers arbitrarily? Every dynamically allocated object is allocated in one place, by one owner. And it should be that one owners responsibility to ensure the object is deleted again.
In some cases, you may want to transfer ownership to another object or component, in which case the responsibility for deleting also changes.
And sometimes, you just want to forget about ownership and use shared ownership: everyone who uses the object shares ownersip, and as long as at least one user exists, the object should not be deleted.
Then you use shared_ptr.
In short, use RAII. Don't try to manually delete objects.
There are some very rare cases where you might not be able to use a smart pointer (probably dealing with old code), but cannot use a simple "ownership" scheme either.
Imagine you have an std::vector<whatever*> and some of the whatever* pointers point to the same object. Safe cleanup involves ensuring you don't delete the same whatever twice - so build an std::set<whatever*> as you go, and only delete the pointers that aren't already in the set. Once all the pointed-to objects have been deleted, both containers can safely be deleted as well.
The return value from insert can be used to determine whether the inserted item was new or not. I haven't tested the following (or used std::set for a while) but I think the following is right...
if (myset.insert (pointervalue).second)
{
// Value was successfully inserted as a new item
delete pointervalue;
}
You shouldn't design projects so that this is necessary, of course, but it's not too hard to deal with the situation if you can't avoid it.
It is not possible to know whether the memory referenced by a pointer has already been deleted, as in your case.
If you can not use a library with smart pointers, that do reference counting, and you can not implement your own reference counting schema (if indeed you need to do what you describe in your post) try to call realloc on the pointers.
I have read in other posts that depending on the implementation the call to realloc may not crash but return back a null pointer. In this case you know that the memory referenced by that pointer has been freed.
If this works as a dirty solution, it will not be portable, but if you have no other option, try it. The worse of course will be to crash your application :)
I would say that some times, smart pointers can actually slow down your application, albiet not by a lot. What I would do is create a method, like so:
void safeDelete(void **ptr)
{
if(*ptr != NULL)
{
delete ptr;
*ptr = NULL;
}
}
I'm not sure if I did it 100% correctly, but what you do is you pass the pointer into this method that takes the pointer of a pointer, checks to make sure the pointer it points to isn't set to NULL, then deletes the object and then sets the address to 0, or NULL. Correct me if this isn't a good way of doing this, I'm also new to this and someone told me this was a great way of checking without getting complicated.

NULL pointer is the same as deallocating it?

I was working on a piece of code and I was attacked by a doubt: What happens to the memory allocated to a pointer if I assign NULL to that pointer?
For instance:
A = new MyClass();
{...do something in the meantime...}
A = NULL;
The space is still allocated, but there is no reference to it. Will that space be freed later on, will it be reused, will it remain on stack, or what?
This is a classic leak.
As you say, the memory remains allocated but nothing is referencing it, so it can never be reclaimed - until the process exits.
The memory should be deallocated with delete - but using a smart pointer (e.g. std::auto_ptr or boost::shared_ptr (or tr1::shared_ptr) to wrap the pointer is a much safer way of working with pointers.
Here's how you might rewrite your example using std::auto_ptr:
std::auto_ptr a( new MyClass() );
/*...do something in the meantime...*/
a.reset();
(Instead of the call to reset() you could just let the auto_ptr instance go out of scope)
Under most circumstances, that will cause a memory leak in your process. You have several options for managing memory in C++.
Use a delete to manually free memory when you're done with it. This can be hard to get right, especially in the context of exception handling.
Use a smart pointer to manage memory for you (auto_ptr, shared_ptr, unique_ptr, etc.)
C++ does not come with a garbage collector, but nothing prevents you from using one (such as the Boehm GC) if you want to go down that route.
That is a memory leak. You have to delete memory you allocate manually.
A = new MyClass();
{...do something in the meantime...}
A = NULL;
The way I keep track of it is that there are two separate objects. Somewhere on the heap, a MyClass instance is allocated by new. And on the stack, there is a pointer named A.
A is just a pointer, there is nothing magical about out, and it doesn't have some special connection to the heap-allocated MyClass object. It just happens to point to that right now, but that can change.
And on the last line, that is exactly what happens. You change the pointer to point to something else. That doesn't affect other objects. It doesn't affect the object it used to point to, and it doesn't affect the object (if any) that it is set to point to now. Again, A is just a dumb raw pointer like any other. It might be NULL, or it might point to an object on the stack, or it might point to an object on the heap, or it might be uninitialized and point to random garbage. But that's all it does. It points, it doesn't in any way take ownership of, or modify, the object it points to.
You need to delete A;
For regular objects setting the pointer to NULL does nothing but invalidating the pointer, the object is still around in memory, this is particularly true if you notice that you may have more than one pointer to the same object, changing one shouldn't affect the others.
On most modern OSs, the application's memory will be reclaimed at exiting the application. Meanwhile, you have a memory leak.
As per Phil Nash's comment, for every new, there is a corresponding delete, likewise, for every malloc, there is a corresponding free. If the corresponding delete/free is not there, you have a leak.
Hope this helps,
Best regards,
Tom.
C++ does't have garbage collector, like some other languages has (Java, C#, ...) so you must delete allocaled objects yourself.
No, it will be lost to the process forever. You will have a memory leak. If you keep doing this, your program will eventually run out of memory!! To avoid this, delete the object when you no longer need it.
Often people will set the pointer to NULL after deleting it, so that other parts of the program can verify that the object has been deleted, and thereby avoid accessing or deleting it again.
Variables stored on the stack, are the local variables of each function, e.g. int big[10];
Variables stored on the heap, are the variables which you initiated using explicit memory allocation routines such as malloc(), calloc(), new(), etc.
Variables stored on the stack have a lifetime that is equal to the lifetime of the current stack frame. In English, when the function returns, you can no longer assume that the variables hold what you expect them to hold. That's why its a classic mistake to return a variable that was declared local in a function.
By assigning NULL to the pointer you will not free allocated memory. You should call deallocation function to free allocated memory. According to C++ Standard 5.3.4/8: "If the allocated type is a non-array type, the allocation function’s name is operator new and the deallocation function’s name is operator delete". I could suggest the following function to safely delete pointers (with assigning NULL to them):
template<typename T>
inline void SafeDelete( T*& p )
{
// Check whether type is complete.
// Deleting incomplete type will lead to undefined behavior
// according to C++ Standard 5.3.5/5.
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);
delete p;
p = NULL;
}