From my understanding, when you allocate objects on the heap you use
Object* dynamicobject = new Object();
When I call delete I go
delete dynamicobject
I'm confused because I delete the pointer to the instance of that object, but along my line of thinking, you need to actually delete the object in memory itself which requires you to dereference the pointer like
delete *dynamicobject
but this is incorrect.
If you want to change the object a pointer points to, it needs to be dereferenced, and I assumed that the same applied for deletion, but it seems only the pointer can be deleted.
If you do
delete *dynamicobject;
the value given to the delete operator is the value in the dynamic memory location, not the location itself. The delete operator needs to know where the dynamic memory is, so it can reclaim it.
For example, suppose you do:
int *dynamic_int = new int;
*dynamic_int = 10;
If you then did:
delete *dynamic_int;
the delete operator would receive the integer value 10. That doesn't provide the information it needs to reclaim the dynamic memory where that value is stored. But if you do
delete dynamic_int;
the delete operator receives the address of that dynamic memory, and it can reclaim it.
The operators are parallel. new returns a pointer to newly-allocated memory. delete takes a pointer to allocated memory and deletes it. In other words, delete (new ...()) works.
Maybe it would help to consider that delete fundamentally has to work with memory somehow, and not with an object, per se. Thus it needs not only the object but also the object's memory location.
I think you are thinking about destructing the object. When you call new, memory is allocated for the object and its address is returned as a pointer. That pointer is a unique identifier recording exactly which area of memory needs to be deallocated when the object is deleted.
So delete needs to be given the pointer to the memory to deallocate.
But that doesn't kill the object. Killing the object happens by running the destructor and this is where the pointer is dereferenced.
The destructor function is, of course ~Object() {}.
So delete will dereference the pointer to access the actual memory of the object by running the destructor function. After the destructor has run on the dereferenced object the memory address that the object occupied is released back to the runtime system.
So delete needs the pointer which gets dereferenced to destruct the object itself and is then used to determine exactly what memory to release.
delete dynamicobject; does not delete the pointer dynamicobject. Rather, it deletes the object that dynamicobject points to.
You don't have to (and can't) write delete *dynamicobject;, presumably for similar reasons to why you don't have to write dynamicobject = &new Object;.
You only deal in pointers, since dynamic memory allocation is just a big linked list of blocks. When you request a block of size n, the allocator searches the linked list for a block that satisfies the request. When the allocator finds the block, it returns a pointer to said block--that is, the address of the first byte in the block.
Freeing memory simply returns the block into the linked list, so that when you try to allocate memory again, that block may be reused.
All the allocator needs to know is the address of the first byte and the size. That's why it deals only in pointers.
Related
I am not sure what exactly the command delete does in c++? As far as I know, to free memory I have to use delete on objects, that I previously instantiated with new, like:
Obj* object = new Obj();
delete object;
But does delete actually deletes data from my objects, does it in any way alter the object and data inside the object itself OR does it just call the corresponding destructor? If the destructor is empty, does useing delete have any consequences to the object? The reason for this question is as follows:
If I just delete objects this way, the pointer gets invalid, and my program does crash. So, I think I should just call the destructor with the delete command and take further steps inside the destructor function do actually do the cleanup and to be sure that other objects refering to this object know that the pointer is truly invalid.
Besides calling the destructor, the delete operator deallocates the memory that was previously allocated by new. This memory goes back to the available pool of memory that can be allocated.
This also means that object now points to invalid memory and any attempt to use it, or any other pointer that pointed to it, will invoke undefined behavior. This is probably what is happening in your program.
So your progam most likely has an issue with who "owns" the pointer. You shouldn't be calling delete on a pointer value that is still being used elsewhere in your program.
I'm trying to understand exactly what happens to deleted variables in c++. Let's say I have something like the following.
MyObject * obj;
for (int i = 0; i < 100000000; i++){
obj = someMethodThatReturnsNewMyObject();
obj->doSomething();
delete obj;
}
Now, upon instantiation, obj is a pointer to a MyObject object. It is first initialized by the line obj = someMethodThatReturnsNewMyObject();. Then some method is called just for fun, and obj is deleted. Now I know when something is deleted like this, the memory space that it is pointing to is expunged, and the pointer is set to point an nothing.
But, then when the for loop comes back around, I re-initialize the pointer, causing it to allocate a new memory space and obj then points at this new space instead. But, at no point was the pointer itself removed from memory. Throughout the loop it only ever points at whatever I tell it to point to or points at nothing (upon deletion).
My question then, is this: When does the pointer itself, that is, the memory space taken up by the pointer, get deleted and why is it not under my requirements to have to delete that if I am required to delete the memory pointed at?
The pointer (the variable obj) has automatic storage duration – just like the variable i. The compiler will emit code to automatically allocate memory for such a variable and release it when it goes out of scope; after invoking any destructor. This memory will come from the stack at run-time, which makes it extremely fast to allocate and free.
By the way, calling delete obj does not “set the pointer to point to nothing”. At least if you mean by this that the pointer is modified. It will continue to have whatever value it had before but that value will no longer point to a valid memory location.
Now I know when something is deleted like this, the memory space that it is pointing to is expunged,
What the run time environment does with the memory is not specified by the language. The language only specifies that using that memory is undefined behavior.
and the pointer is set to point an nothing.
That is not correct. The value of the pointer remains what it was. It points to memory that is not valid any more.
When does the pointer itself, that is, the memory space taken up by the pointer, get deleted
It's implementation specific. In common implementations, the memory gets reclaimed by the run time environemnt when the function returns. As per the language, the life of the pointer ends when the scope in which it is defined ends. Using the memory occupied by the pointer after its scope has ended is undefined behavior.
If you had:
MyObject** ptr = NULL:
for (int i = 0; i < 100000000; i++){
// obj is defined in the scope of the for loop.
// It's life ends when the for loop ends.
MyObject* obj = someMethodThatReturnsNewMyObject();
obj->doSomething();
delete obj;
// Make ptr point to the address of obj.
ptr = &obj;
}
*ptr = NULL; // This is undefined behavior since ptr
// points to memory that is not valid any more.
The pointer itself gets deleted when the program terminates. You're probably not being required to delete the pointer itself because you're reusing it, and it occupies the same amount of space in memory for the duration of its existence. The memory being pointed to, however, is being recycled with each iteration of your loop in order to keep from filling your memory up. This wouldn't be a problem if your for loop only runs a few times, but if you're looping a lot without de-allocating that space it could potentially fill up your memory and crash your program.
The delete keyword deletes the memory that a pointer points to. It does not delete the pointer itself.
How a pointer is deallocated depends on where it is declared. If your example code is in a method/function, it gets declared on the stack and is released when the method/function returns. If the pointer is a global variable, then it would live the life of your program.
the memory space that it is pointing to is expunged, and the pointer is set to point an nothing.
Forgiving the typo, the pointer is not changed. It still points to where the object was before delete was called. After deletion, using the object through the pointer is "bad". It might work and access the previous content. It might access total garbage (like from memory reuse). Calling methods through the pointer could well jump into space, hopefully segfalting instead of reformatting your disks.
You do want the pointer variable to remain. It gets used each iteration. delete is useful to free the memory (and run any destructors) in the object a pointer points to.
when you do : delete obj
Then you are marking the memory location pointed by obj to be deleted and will be returned to the system.
Its a bit tricky here larger chucks are mmap'd and smaller ones are managed by heap and deleting it will not be reflected in the system unless it is the topmost. If it is not the topmost in the heap, then brk/sbrk will not be moved and that will be reused when you next ask/allocate a size same or smaller than then one that is marked to be deleted. The algorithm is bit more complicated but that is the gist.
In your code, in the second iteration obj can point to a entirely different chunk/block.
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.
what is the difference between deleting a pointer, setting it to null, and freeing it.
delete ptr;
vs.
ptr=NULL;
vs.
free(ptr);
Your question suggests that you come from a language that has garbage collection. C++ does not have garbage collection.
If you set a pointer to NULL, this does not cause the memory to return to the pool of available memory. If no other pointers point to this block of memory, you now simply have an "orphaned" block of memory that remains allocated but is now unreachable -- a leak. Leaks only cause a program to crash if they build up to a point where no memory is left to allocate.
There's also the converse situation, where you delete a block of memory using a pointer, and later try to access that memory as though it was still allocated. This is possible because calling delete on a pointer does not set the pointer to NULL -- it still points to the address of memory that previously was allocated. A pointer to memory that is no longer allocated is called a dangling pointer and accessing it will usually cause strange program behaviour and crashes, since its contents are probably not what you expect -- that piece of memory may have since been reallocated for some other purpose.
[EDIT] As stinky472 mentions, another difference between delete and free() is that only the former calls the object's destructor. (Remember that you must call delete on an object allocated with new, and free() for memory allocated with malloc() -- they can't be mixed.) In C++, it's always best to use static allocation if possible, but if not, then prefer new to malloc().
delete will give allocated memory back to the C++ runtime library. You always need a matching new, which allocated the memory on the heap before. NULL is something completely different. A "placeholder" to signify that it points to no address. In C++, NULLis a MACRO defined as 0. So if don't like MACROS, using 0 directly is also possible. In C++0x nullptr is introduced and preferable.
Example:
int* a; //declare pointer
a = NULL; //point 'a' to NULL to show that pointer is not yet initialized
a = new int; //reserve memory on the heap for int
//... do more stuff with 'a' and the memory it points to
delete a; //release memory
a = NULL; //(depending on your program), you now want to set the pointer back to
// 'NULL' to show, that a is not pointing to anything anymore
well, if you created object dynamically(with 'new'), setting pointer to any value does not delete object from memory - and you get a memory leak.
As with any indirection, there are two objects involved when using pointers: the referrer (the pointer, in your example ptr) and the referenced object (what it points to, *ptr). You need to learn to differentiate between them.
When you assign NULL to a pointer, only the pointer is affected, the object it refers to is left alone. If the pointer was the last one pointing to that object, you have lost the last referring pointer pointing to it and thus cannot use it anymore. In C++, however, that does not mean the object will be deleted. C++ does not have a garbage collection. So the object is leaked.
In order for objects to be deleted, you will have to delete them manually by passing their address (stored in a pointer) to the delete operator. If you do this, only the object referred to will be affected, the pointer is left alone. It might still point to the address where the object resided in memory, even though that isn't usable anymore. That is called a dangling pointer.
When you create an object using new, you need to use delete to release its memory back to the system. The memory will then be available for others to reuse.
int* a = new int;
delete a;
NULL is just a pre-defined macro that can be assigned a pointer to mean that it does not point to anything.
int* a = new int;
a = NULL;
In the above case, after allocating storage for a, you are assigning NULL to it. However, the memory previously allocated for a was not released and cannot be reused by the system. This is what we call memory leak.
int * ptr = null;
Calling free(ptr) will do nothing. According to standard if given pointer is null then no action happens.
Using delete p will also do nothing. C++ standard says that no action will happen because it points to nothing and no type is available.
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;
}