C++ Pointer and Memory Allocation - c++

I am teaching myself C++. It is my first programming language and I am struggling with the wording associated with the memory allocation of pointers.
Consider this statement:
int *p;
int x;
p = &x;
*p = 8;
Value
&p 1400
p 1800
*p 8
x 8
&p is the memory address of p.
p is the memory address pointed to by the pointer p.
*p is the value of the memory address pointed to by the pointer p.
I understand this. However the book states:
p = &x stores the address of x in p. However, no new memory is allocated.
This is confusing. Memory has been allocated, else p would be undefined.
Now consider this statement:
int *p;
p = new int;
*p = 28;
Here, you dont need an additional variable to make *p valid and meaningful, because memory has been allocated.
So, I guess my question is:
What is the author's meaning of his statement, "Memory is not allocated.", when considering the code block?

p = &x stores the address of x in p. However, no new memory is allocated.
100% true. All of the allocation was done in the preceding two lines.
int *p; // allocation of p here
int x; //allocation of x here
p = &x; // no allocation here.
p = &x; is just an assignment of the location of previously allocated memory to a previously allocated pointer. Whether storage is allocated on the stack, the heap, or whatever the current system uses instead of a stack or heap is irrelevant.
For the second example,
int *p; //allocation of p here
p = new int; // allocation of one nameless int AND assignment of that int to p here
*p = 28; // no allocation

Generally the single word 'allocated' is used as an abbreviation for 'allocated out of heap storage using the 'new' keyword, a library routine such as 'malloc', or some other such mechanism (directly or indirectly)'.
Here the statement 'p = &x;' means that the value of p is set to the storage address of x, which is allocated on the stack. Since the stack storage is managed automatically rather than at the programmer's discretion, we choose not to refer to this as 'allocated' in colloquial usage.

Memory is allocated on the stack when you first declare the variable. Here, memory is allocated in
int *p;
int x;
So, p = &x; stores the memory address of x in the previously allocated memory for p on the stack.

"p = &x stores the address of x in p. However, no new memory is allocated."
I think this probably just means that in this particular statement p takes the address of x and no new memory is allocated for x. The memory for x was probably earlier allocated but initialization of p doesn't allocate new memory for x.
But in the latter statement
int *p;
p = new int;
*p = 28;
p points to a new chunk of memory that has been allocated because it is initialized with "new int".

"p = &x stores the address of x in p. However, no new memory is allocated." Because 'x' was created on the stack, not on the heap (just like the variable 'p', and all other 'local variables'). It seems your 2nd example is incorrect, but I'm not 100% sure.

Author probably refers to heap allocation. Both p and x are allocated on stack, which is really just incrementing (or decrementing, depending on machine type) the stack pointer. They're deallocated when they go out of scope. OTOH, new int allocates it from heap memory, which probably takes more time to do, but can live longer than it's scope: you manually deallocate it using delete. Either case, pointer works well: this might be non-evident at first, but you can take the address of a variable on the stack or one that's allocated from the heap using the same type.

Well I got that book and the explanation provided by others is correct. Just adding mine too.
When you compile a function, unless it is a variable argument one, the frame size and format is already known to compiler. Now when you call this function, compiler reserves the memory for this frame on the stack above (or below) the caller function. You can see this happening yourself.
void fun(){
int a,b;
printf("addr fun &a=%u, &b=%u",&a,&b);
callfun();
}
void callfun(){ int c;
printf("addr callfun &c=%u",&c);
}
On most architectures, address may seem decreasing - but logically by calling calllfun(), we created a frame above previous frame.
So, one can say that memory for these variables was created transparently and programmer never cared for that. When the stack grows, more memory is used, and freed when the function calls come closer to the main entry point function. But in other case, when you use new operator, programmer explicitly asks for memory in addition to what has been already allocated on the stack. This is fulfilled from another region in program's address space called heap. OS provides facility for doing this.
In your case, author just said that since the function carrying all these variables was already called, memory has already been allocated (on stack) in the process and NO NEW memory was created. However, you may use new operator to allocate more memory if you want.

Related

Can a pointer returned by new have the same value as a deleted pointer returned by a previous use of new

Will both the cout statement always print the same value?
#include<bits/stdc++.h>
using namespace std;
int main(){
int* p = new int();
*p = 54;
cout<<p; // it displays the address of int in heap();
delete(p);
p = new int[4];
cout<<p; // it displays the address of first block of memory, of array in heap;
return 0;
}
Will both the cout statement always print the same value?
No. After the delete(p) the memory allocated by the first new expression is deallocated and therefore free to be reused for a later evaluation of a new expression, but there is no guarantee at all that it will be.
That you are reusing the same pointer variable p is irrelevant. It simply stores the address of the storage location returned by the new expressions. You could have used different pointer variables to store the addresses in the same way.
It is also irrelevant that you create a int in the first new expression and a int[4] in the second. Both of the new expressions happen to return a int* which can be stored in the same variable, but nothing would change about the above if you had used simply int in both, or had used completely different types and a pointer variable of type void*.
Will both the cout statement always print the same value?
No. The purpose of delete is to allow memory to be reused so it's possible that the next allocation returns a value just deleted.
But how new manages memory is unspecified.
For example it my be managing pools of different sizes so asking for space 4 integers may not be from the same pool as 1.
It may be that on your platform that simple program will always return the same value twice. But you should regard that as entirely incidental and not something useful.
Whilst in this simple case you may observe the same address assigned to p that is not generally the case. The allocator will allocate a block of memory on a first fit basis, and it is likely in this case that the first available block of the requisite size will be at the same address as the block just released.
If you were to change the example to:
delete(p);
volatile int* dp = new int[4] ;
p = new int[4];
cout<<p;
You will almost certainly observe that the pointer value of p is no longer the same. Moreover if you were to have:
int* p1 = new int[4] ;
int* p = new int[4];
int* p2 = new int[4];
cout << p1;
cout << p2 ;
cout << p ;
delete[] p ;
p = new int[Ox8000];
cout << p;
It is likely that the heap will be fragmented such that the second p allocation will not fit in the space released by the delete.
The delete does not remove the memory from existence, it rather marks the block as available for re-use, returning it to the heap (and coelesing it with adjacent free memory). What you are observing when you get the same pointer value is simple reuse of the space returned to the heap.

Live on heap or stack when use new operator within a function block?

For instance:
void Func()
{
int* i = new int; // the simplest case
vector<int*> v = new vector<int*>; // another case, not sure if **new** is using correctly here
vector<int*>* vPointer = new vector<int*>;
}
void main()
{
Func();
}
So, if I allocate dynamic memory(by using new operator) for local variables in functions,
Do they live on heap or stack?
when the program exits the function, are they still dangling around on heap or destroyed as function variables?
Can I use new operator on non-pointer types? How to delete (or return back the allocated heap memory) it later?
Thank you!
int i = 3;
this creates an object of type int on the stack. (The C++ standard uses the term "automatic storage", and I'm usually a stickler for proper use of formal terms, but "stack" and "heap" are deeply embedded in programming vocabulary, so "stack" and "heap" are just fine as technical terms).
int *ip = 0;
this creates an object of type int* on the stack. ip holds a null pointer.
int *ip = new int;
this creates an object of type int* on the stack, just like the previous one. It holds a pointer to memory on the heap (see earlier parenthetical; the formal term is "free store"). You know that the memory is on the heap because that's what operator new does.
When you're finished with the heap memory you have to release it:
delete ip;
if you don't delete it and the function that created it returns, the local variable (ip) that held the pointer is gone. The memory has been allocated and it hasn't been freed, so unless you copied the pointer to some place else, you have no way to get at the memory you allocated. That's called a "memory leak".

Deleting Pointers

I wanted to ask, is dynamically creating a pointer, and then changing a pointer address to something else still deleting the original allocated space?
for example:
int main()
{
int c = 50;
// Memory leak
int * q = new int;
q = & c;
delete q;
}
What exactly is getting deleted or happening?
Thanks!
What exactly is getting deleted or happening?
Memory leaking and undefined behaviour.
When you do q = & c; you are losing your only tracking of the memory allocated by new int. Noone keeps track of this for you, there is no garbage collector, it is simply lost and cannot be recovered.
When you then do delete q; (where q is assigned to &c) you are deleting memory that you didn't allocate, and worse you are deleting memory on the stack. Either of these will result in undefined behavior.
This is an excellent preface into why you should avoid using pointers in circumstances where you don't need them. In this case, there is no reason dynamically allocate your int. If you really need a pointer, use a c++11 smart pointer (or boost if you don't have c++11). There are increasingly rare cases where you really do need a raw c type pointer. You should read Effective Modern c++ Chapter 4 for excellent detail on this subject.
is dynamically creating a pointer, and then changing a pointer address to something else still deleting the original allocated space?
No. delete will deallocate the memory to which its operand points. You must delete the same block of memory that you obtained from new.
int c = 50;
int * q = new int;
int * r = q;
q = & c;
delete q; // WRONG! q points to something you didn't get from new
delete r; // OK! p points to the block you got from new
To be even more clear, delete doesn't care about what variable it operates on, it only cares about what that variable points to. In the last line above, r points to the block that was originally pointed to by q and allocated by new, so you can safely delete it. q points to statically allocated memory, not something you got from new, so you can't delete it.
Instead of changing where q points, though, you can copy the value you want into the space that q points to:
int c = 50;
int * q = new int;
*q = c;
delete q; // OK! q still points to the same place
Here you're changing the value stored in the location to which q points, but you're not changing q itself. q still points to the block you got from new, so it's safe to delete it.
You code will (try to) delete c. There's no memory management or anything like that in C/C++. delete will try to delete whatever the given pointer points to, and and whatever is not deleted (either by calling delete for variables created with a call to new, or by leaving the scope for local variables) will remain in memory until the program ends.
Notice that trying to delete a local variable will propably cause a crash, since delete actually checks (in a very basic manner) what it deletes - at least to know how much memory has actually been allocated at that address. And at this check, it will propably notice that c doesn't include this information, or that it isn't even at the right end of the memory space, so it will crash.
It will crash because c is created in the stack memory section. If you're lucky and the program didn't crash you aren still leaking memory because the q reference is lost.
First answer is to your question:-
I wanted to ask, is dynamically creating a pointer
We don't create a pointer dynamically. Pointers are just a variable like other variable in C and C++. Difference is, pointer is a variable which can store the address of a particular memory location. In run time you just dynamically allocate memory and assign the address of first address location of that memory size into it.
Now what will happen if you don't delete/free the memory and assign a new address to it. In that case memory will not be release/freed and that can not be use anymore as that will never be marked as free by OS. When you free/delete memory O/S mark that area as free to use, and your running process can utilize it in future. That is call proper memory management. Improper memory manage leads your program to memory leak.

Some basic pointer questions

I have a few silly questions (probably for most), it's less about 'how' do I do them and more about 'why' do they work this way? I know you are not supposed to ask multiple questions, but these are fairly small and related to one topic. Seems like it'd be a waste to separate them out.
I understand for the most part pointers, and the operators themselves. (Although I am curious why the * is called the de-reference operator, since isn't it referring to a reference of what it contains?)
I.e:
int x = 25;
int *p = &x;
So & makes sense, since *p is a place in the stack of type int that contains the address of x (which we know is 25).
So by saying *p are we 'referencing' the address of p which is pointing to the 25. Maybe it's just an English semantics thing? Maybe someone can explain why it's called 'de-reference'?
Take this valid code sample:
int *p = new int;
*p = 5
Simple enough, we're making a new place in the stack with the size of an int pointer (whatever that may be). p will contain some address that has a 5 for a value.
Thing is, I haven't actually declared anything that's storing a 5, so what the heck is p pointing to? I mean, this does indeed work, but I never made a int x = 5 or anything like that, and gave the address to p to point to? How does it even know?
p contains an address that points to something, but I never made that 'address' it's pointing to? Does the compiler just know to create another address somewhere else? (Sorry if this is a really stupid question.)
I was reading on here about some memory leaks on another question:
A *object1 = new A();
pretending A is a class first of all. Someone was saying the object1 stores the value of A. Isn't that incorrect? Doesn't object1 store the address of what new A() created and is pointing to it?
Because delete object1 deletes the pointer, which points to the new A() (but from the other question delete object1 would indeed be the correct syntax. So does that leave the new A() hanging out there? Or does it get automatically deleted? (As you can tell I'm a bit confused.)
If delete object1 does indeed delete what the pointer is pointing to and not the pointer itself, doesn't this just leave a dangling pointer?
Here
int x = 25;
int *p = &x;
* is not the dereferencing operator. It's part of the type of p. It basically says that p is a pointer.
Here
int *p = new int;
*p = 5;
The key is new int. It dynamically creates an int and returns it's address, so p now points to that address. *p = 5 (btw, here * is the dereferencing operator) modifies the value -- of that dymanically allocated int -- to 5
Indeed object1 holds the address of the newly created A. Since we're here we should clarify this: A is a (user defined) type. So it makes no sense to say that A has a value. Objects of type A have value.
delete p doesn't delete a pointer. It does 2 things:
Destroys an object created by a new-expression
Deallocates storage previously allocated by a matching operator new
The pointer isn't actually changed, i.e. it still points to the same address. Only now that address isn't allocated, i.e. can't be dereferenced anymore.
You can further refer to this SO answer - Static, automatic and dynamic storage duration to further understand objects, pointers, new/delete.
1: I'm not sure what you're implying when you say "which we know is 25". The address of x is not 25, rather that is the value of x. You do not set the address of x in a statment like int x = 25
But to answer your question, p is a reference, which is to say its value is an address. Accessing the value stored at the address p requires the *p, which dereferences the pointer.
2: You have allocated memory for p; you executed a new. You have allocated 4 (or 8) bytes of memory for a new integer on the heap, so p is pointing to a newly allocated block of memory. Saying *p = 5; tells the compiler to set the value stored at that address to 5.
3: Your assumption is correct; object1 does not store the value of a new A, rather points to a block of memory equivalent in size to aninstance of an object of size A.
delete object1; Does not delete the pointer. The pointer is simply an integer on the stack, rather it gives back the allocated memory for that pointer back to the system. A as you knew it is deleted, but the pointer still exists, and using it at this point is undefined behavior. You are correct in assuming you have a dangling pointer now, that is why you should always set deleted pointers to NULL.

Does a pointer point to the stack or heap after using delete?

In these lines of C++ code:
int * p = new int(33);
delete(p);
*p = 13;
cout << *p << endl;
The output is 13;
P points to an address on the heap initially, then I use the delete keyword to deallocate p's assigned memory address, but can still assign the memory address a value of 23; Is this the same address on the heap that p pointed to after "int * p = new int(33)" or does p point to an address on the stack after using delete(p)?
It still points to the same address (you can tell by printing the address). You'll sometimes see people assign NULL or nullptr or 0 to a pointer after freeing the memory to ensure they don't try to try to dereference the freed memory because it doesn't get assigned null for them. This allows them to have code such as this:
if (p != nullptr)
//do something with p, it hasn't been freed and set to nullptr
That's hard to do if it isn't set to null when it is freed, but do note that a smart pointer provides a safer, consistent alternative to the above.
The reason you're getting the correct output is undefined behaviour. It could crash, it could blow up, or it could work. I guess it chose to work.
Deleting p signals to whoever manages the memory (the OS) that the underlying space is now free to be re-allocated by someone else for their own use. p, however, still points to the same memory location and can be dereferenced to obtain the value of what's in that memory -- note that since that memory may now be used by someone else, the underlying bits might be different from what they were before.
Yes, it still points to the heap but that memory location is not stable. The OS could reclaim it any time so the value at that memory location is not guaranteed to be what you set it to.
Also, as far as I know, all dynamic memory allocation happens on the heap, not the stack. Stack is reserved for parameters and local variables.