# include <iostream>
int main()
{
using std::cout;
int *p= new int;
*p = 10;
cout<<*p<<"\t"<<p<<"\n";
delete p;
cout<<*p<<"\t"<<p<<"\n";
return 0;
}
Output:
10 0x237c010
0 0x237c010
Here after deleting p, why the pointer p retains its value? Doesn't delete frees the pointer p?
What exactly is meant by 'freeing the pointer'?
Does 'delete p' simply mean '*p = 0'?(which seems from the output)
Here after deleting p, why the pointer p retains its value?
It's how the language is designed. If you want the pointer you hold to be zeroed, you'll need to assign it zero yourself. The pointer p is another piece of memory, separate from the allocation/object it points to.
Doesn't delete frees the pointer p?
It calls the destructor the object and returns the memory to the system (like free). If it is an array (delete[]), destructors for all elements will be called, then the memory will be returned.
What exactly is meant by 'freeing the pointer'?
When you want a piece of memory from the system, you allocate it (e.g. using new). When you are finished using it, you return it using the corresponding free/delete call. It's a resource, which you must return. If you do not, your program will leak (and nobody wants that).
In order to understand what freeing memory means, you must first understand what allocating memory means. What follows is a simplified explanation.
There exists memory. Memory is a large blob of stuff that you could access. But since it's global, you need some way to portion it out. Some way to govern who can access which pieces of memory. One of the systems that governs the apportionment of memory is called the "heap".
The heap owns some quantity of memory (some is owned by the stack and some is owned by static data, but nevermind that now). At the beginning of your program, the heap says that you have access to no heap-owned memory.
What new int does is two fold. First, it goes to the heap system and says, "I want a piece of memory suitable to store an int into." It gets back a pointer to exactly that: a piece of the heap, into which you can safely store and retrieve exactly one value of type int.
You are now the proud owner of one int's worth of memory. The heap guarantees that as long as its rules are followed, whatever you put there will be preserved until you explicitly change it. This is the covenant between you and the almighty heap.
The other thing new int does is initialize that piece of the heap with an int value. In this case, it is default initialized, because no value was passed (new int(5) would initialize it with the value 5).
From this point forward, you are legally allowed to store exactly one int in this piece of memory. You are allowed to retrieve the int stored there. And you're allowed to do one other thing: tell the heap that you are finished using that memory.
When you call delete p, two things happen. First, p is deinitialized. Again, because it is an int, nothing happens. If this were a class, its destructor would be called.
But after that, delete goes out to the heap and says, "Hey heap: remember this pointer to an int you gave me? I'm done with it now." The heap system can do whatever it wants. Maybe it will clear the memory, as some heaps do in debug-builds. In release builds however, the memory may not be cleared.
Of course, the reason why the heap can do whatever it wants is because, the moment you delete that pointer, you enter into a new agreement with the heap. Previously, you asked for a piece of memory for an int, and the heap obliged. You owned that memory, and the heap guaranteed that it was yours for as long as you wanted. Stuff you put there would remain there.
After you had your fun, you returned it to the heap. And here's where the contract comes in. When you say delete p, for any object p, you are saying the following:
I solemnly swear not to touch this memory address again!
Now, the heap might give that memory address back to you if you call new int again. It might give you a different one. But you only have access to memory allocated by the heap during the time between new and delete.
Given this, what does this mean?
delete p;
cout << *p << "\t" << p << "\n";
In C++ parlance, this is called "undefined behavior". The C++ specification has a lot of things that are stated to be "undefined". When you trigger undefined behavior anything can happen! *p could be 0. *p could be the value it used to be. Doing *p could crash your program.
The C++ specification is a contract between you and your compiler/computer. It says what you can do, and it says how the system responds. "Undefined behavior" is what happens when you break the contract, when you do something the C++ specification says you aren't supposed to. At that point, anything can happen.
When you called delete p, you told the system that you were finished using p. By using it again, you were lying to the system. And therefore, the system no longer has to abide by any rules, like storing the values you want to store. Or continuing to run. Or not spawning demons from your nose. Or whatever.
You broke the rules. And you must suffer the consequences.
So no, delete p is not the equivalent of *p = 0. The latter simply means "set 0 into the memory pointed to by p." The former means "I'm finished using the memory pointed to by p, and I won't use it again until you tell me I can."
Here after deleting p, why the pointer p retains its value? Doesn't delete frees the pointer p?
It frees the memory the pointer points to (after calling any appropriate destructor). The value of the pointer itself is unchanged.
What exactly is meant by 'freeing the pointer'?
As above - it means freeing the memory the pointer points to.
Does 'delete p' simply mean '*p = 0'?(which seems from the output)
No. The system doesn't have to write anything to the memory that's freed, and if it does write something it doesn't have to write 0. However, the system does generally have to manage that memory in some way, and that might actually write to the area of memory that the pointer was pointing to. Also, the just-freed memory can be allocated to something else (and in a multi-threaded application, that could happen before the delete operation even returns). The new owner of that memory block can of course write whatever they want to that memory.
A pointer that is pointing to a freed block of memory is often known as a 'dangling' pointer. It is an error to dereference a dangling pointer (for read or write). You will sometimes see code immediately assign a NULL or 0 to a pointer immediately after deleting the pointer, sometimes using a macro or function template that both deletes and clears the pointer. Note that this won't fix all bugs with dangling pointers, since other pointers may have been set to point to the memory block.
The modern method of dealing with these kinds of problems is to avoid using raw pointers altogether in favor of using smart pointers such as shared_ptr or unique_ptr.
delete p simply frees the memory allocated during a call to the new operator. It does not change the value of the pointer or the content of the deallocated memory.
(Note the following isn't how it actually works so take it with a grain of salt.)
Inside the implementation of new it keeps a list of all available memory when you said "int *p= new int;" it cut a int sized block off of its list of available memory and gave it to you. When you run "delete p;" it gets put back in the list of available memory. If your program called new 30 times without calling delete at all you would get 30 different int sized chunks from new. If you called new then delete 30 times in a row you might (but not necessarily) get the same int sized block. This is because you said you weren't using it any more when you called delete and so new was free to reuse it.
TLDR; Delete notifies new that this section of memory is available again it doesn't touch your variable.
Related
When we declare something dynamically like this
int *ptr = new int [100];
and then change the pointer address (i.e point it to something else)
int pointer[5] = {1,2,1,3,1,};
ptr = pointer ;
now what happens to that memory which contained 100 integers?
is there anyway to regain control of that memory ? and if not, does it lead to a memory leak?
now what happens to that memory which contained 100 integers?
It is "leaked" because you lost the only handle you had to it.
is there anyway to regain control of that memory ?
No, unless you take care to create another handle before re-assigning ptr.
int* ptr = new int[100];
int* ptr2 = ptr;
...
ptr = pointer;
delete [] ptr2;
In real code you would not rely on raw pointers to allocated memory, but rather use whichever RAII type works best for your problem (e.g. std::vector, std::unique_ptr etc.)
In the sample you give, ptr is the only pointer that references the hundred int created by new int [100] (i.e. points at the first element).
Changing the value of ptr does not affect the hundred int. It means that ptr no longer contains the address of the first element.
Practically, after the assignment ptr = pointer, the allocated memory is said to be leaked - it has been allocated, there is no way in standard C++ to access it, and no way in standard C++ to release it (e.g. make the memory it consumes available for reallocation in another new expression).
The only way to keep control of the memory in your case is to store the value of ptr in another variable (or a member of a structure, or an element of an array of pointers, ....) BEFORE reassigning it. If the value of ptr is stored before reassigning ptr, and the place it is stored still exists, the value can be retrieved.
Practically, it would be better to use a standard container (e.g. a std::vector<int>) and not use a new expression in your code. That way, the contents of the container are accessible as long as the container exists (and cease to exist, as far as your program is concerned, when the container does).
Any block of memory allocated with new is unavailable until it is released, either by a corresponding delete or when the process in which the memory was allocated terminates.
The memory allocator actually has no clue about what references you maintain on allocated objects.It just allows you to release the corresponding memory blocks if you manage to provide valid addresses.
How you keep track of these addresses is entirely up to you.
So if for some reason you loose track of a chunk of memory (by overwriting a data pointer as in your example, or simply forgetting to use it at some point to release the memory), you will deprive your system of this bit of memory until the underlying process terminates.
This becomes a memory leak if the "memory lapse" is unintentional, even more so if this occurs repeatedly.
For instance, if you need some data that has the same life span as the process, you can do a one-time allocation and never release the memory (since it will be released automatically upon termination). That could horrify the good practices zealots, but would nevertheless not qualify as a memory leak.
On the other hand, there are other ways of messing up you memory allocator : passing an invalid pointer to delete (including a reference to an already released object, i.e. deleting the same instance of an object more than once, or a pointer to something that was not allocated by new, like a local or global variable) will bring you the wonderful realm of undefined behaviours, which could cause random memory losses, data corruption or nuclear meltdowns.
I was solving some programming exercise when I realised that I have a big misunderstanding about pointers. Please could someone explain the reason that this code causes a crash in C++.
#include <iostream>
int main()
{
int* someInts = new int[5];
someInts[0] = 1;
someInts[1] = 1;
std::cout << *someInts;
someInts++; //This line causes program to crash
delete[] someInts;
return 0;
}
P.S I am aware that there is no reason to use "new" here, I am just making the example as small as possible.
It's actually the statement after the one you mark as causing the program to crash that causes the program to crash!
You must pass the same pointer to delete[] as you get back from new[].
Otherwise the behaviour of the program is undefined.
The problem is that with the someInts++; you are passing the address of the second element of an array to your delete[] statement. You need to pass the address of the first (original) element:
int* someInts = new int[5];
int* originalInts = someInts; // points to the first element
someInts[0] = 1;
someInts[1] = 1;
std::cout << *someInts;
someInts++; // points at the second element now
delete[] originalInts;
Without going into the specifics of a specific implementation here, the intuitive reason behind the crash can be explained simply by considering what delete[] is supposed to do:
Destroys an array created by a new[]-expression
You give delete[] a pointer to an array. Among other things, it has to free the memory it allocated to hold the contents of that array after.
How is the allocator know what to free? It uses the pointer you gave it as a key to look up the data structure which contains the bookkeeping information for the allocated block. Somewhere, there is a structure which stores the mapping between pointers to previously allocated blocks and the associated bookkeeping operation.
You may wish this lookup to result in some kind of friendly error message if the pointer you pass to delete [] was not one returned by a corresponding new[], but there is nothing in the standard that guarantees that.
So, it is possible, given a pointer which had not been previously allocated by new[], delete[] ends up looking at something that really is not a consistent bookkeeping structure. Wires get crossed. A crash ensues.
Or, you might wish that delete[] would say "hey, it looks like this pointer points to somewhere inside a region I allocated before. Let me go back and find the pointer I returned when I allocated that region and use that to look up the bookkeeping information" but, again, there is no such requirement in the standard:
For the second (array) form, expression must be a null pointer value or a pointer value previously obtained by an array form of new-expression. If expression is anything else, including if it's a pointer obtained by the non-array form of new-expression, the behavior is undefined. [emphasis mine]
In this case, you are lucky because you found out you did something wrong instantaneously.
PS: This is a hand-wavy explanation
You can increment a pointer within the block and use that incremented pointer to access different parts of the block, that is fine.
However you must pass Delete the pointer you got from New. Not an incremented version of it, not a pointer that was allocated by some other means.
Why? well the cop-out answer is because that is what the standard says.
The practical answer is because to free a block of memory the memory manager needs information about the block. For example where it starts and ends, and whether adjacent chunks are free (normally a memory manager will combine adjacent free chunks) and what arena it belongs to (important for locking in multithreaded memory managers).
This information is typically stored immediately prior to the allocated memory. The Memory manager will subtract a fixed value from your pointer and look for a structure of allocation metadata at that location.
If you pass a pointer that does not point to the start of a block of allocated memory then the memory manager tries to perform the subtraction and read it's control block but what it ends up reading is not a valid control block.
If you are lucky then the code crashes quickly, if you are unlucky then you can end up with subtle memory corruption.
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.
Dynamically allocating memory in C++ of course can be accomplished using new or delete. If a pointer dynamically allocated using new is no longer needed in the course of a C++ program, delete can be used in order to dynamically free up computer memory. I think, if my memory serves me correctly, that Stroustrep in one of his books on C++ mentions that malloc and alloc in C afford the compiler rather than the programmer the option to "free up" or "create" memory in contrast to the object-oriented "new" and "delete". If I don't delete the pointer, then I'll run into a rather insidious memory leak, which isn't good.
However, merely deleting a pointer--as Carrano, Helman, and Veroff (CHV) note on pages 151-153 in the 2nd edition of Walls and Mirrors--does not get rid of the pointer. Rather, delete empties the contents of the pointer yet leaves the pointer somewhere in the memory space of the computer.
In any event, CHV then say that the pointer must be set to NULL after using delete in order get rid of this "deleted" construct.
Is the assignment operator being overloaded in this case to accept NULL as a Boolean value? In other words, is the compiler telling the computer that it is false that the pointer ought to exist in the memory space, meaning that I'm telling the compiler to physically stop a bunch of electrons occupying a two bit space from running through my computer? Am I missing something here?
merely deleting a pointer does not get rid of the pointer
Indeed not; it destroys the object that the pointer points to, and deallocates the object's memory. The pointer isn't affected, and ends up pointing to invalid memory.
In any event, CHV then say that the pointer must be set to NULL after using delete in order get rid of this "deleted" construct
No, the pointer will still exist after that; but setting it to null will make sure it's not pointing to invalid memory, which is arguably safer. Of course, it's a much better idea to manage dynamic objects with smart pointers, so you never end up with an invalid pointer in the first place.
Is the assignment operator being overloaded in this case to accept NULL as a Boolean value?
No, NULL isn't a boolean value, it's a null pointer constant; a special pointer value which doesn't point to anything.
In other words, is the compiler telling the computer that it is false that the pointer ought to exist in the memory space, meaning that I'm telling the compiler to physically stop a bunch of electrons occupying a two bit space from running through my computer?
Er, what? No, it's just telling the pointer not to point to anything. It certainly doesn't stop any electrons from occupying any spaces.
Am I missing something here?
I think the main idea you're missing is that the pointer and the thing it points to are separate objects, with separate lifetimes. delete will destroy an object with a dynamic lifetime, but not the pointer that's used to refer to it.
A bit of history might help. First, there was C, with malloc, etc. e.g.:
char *ptr = malloc(100);
strcpy(ptr, "hello, world!");
free(ptr);
printf("%s\n", ptr); /* BAD - but will PROBABLY print "hello, world!" */
malloc allocates 100 bytes, the strcpy populated it, and the free() deallocates it. What's involved in "deallocate" simply means that that memory will now be available for reuse by another call to malloc.
free() does NOT reset any pointers, nor clear the memory - hence printf above will probably still print the string as nothing will (probably) have changed. Of course, any programmer writing something like this deserves to be fired.
In order to avoid the bad usage, since free() won't reset the pointers, it's good practice for us to reset them instead as soon as we free some memory :
free(ptr);
ptr = NULL;
printf("%s\n", ptr); /* Now we get a NULL pointer exception - which is what we want */
We WANT the Null-pointer-exception, since after the free() we shouldn't be using the value of ptr.
With C++, all these arguments are the same. delete does a few more things than free - primarily it calls the objects destructors, etc, but the basic's the same. Pointers are not reset, and the memory's still lying around - and you DO want to know if you're accessing memory that's not allocated to you - and the best way of doing that is setting your pointers to null when you delete the object.
Nulling pointer with nullptr or NULL is used to prevent crashes on double deletes, not to free the memory the pointer actually takes (pointer, not memory it is pointing at). The only time when the actual pointer stops existing is the end of a scope.
The lifetime of the pointer itself, like all other variables, is governed by scope.
void someFunc()
{
int* ptr;
}//ptr dies after this bracket
So always please remember to free the memory a pointer points to before it goes out of scope or you`ll never be able to access it again!
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;
}