lI'm running a C++ program on a 64-bit machine. The program dynamically creates objects from different classes. When I print out the value of the pointers (not dereferencing) to those objects using cout, the address of some objects is 48-bits while the address of other objects is 28-bits! I have read that some processors currently only support 48-bits, but why then do I get an output of 28-bits in some cases? What does that even mean?!
Edit:
This is part of a big project. So, I won't be able to post the exact code. But here is what is basically happening. I do realize that the objects need to be deleted to avoid memory leaks.
ClassA *pA = new ClassA();
ClassB *pB = new ClassB();
cout << "Address of ClassA object = " << pA << " , Address of ClassB object = " << pB << endl;
pA = new ClassA();
pB = new ClassB();
cout << "Address of ClassA object = " << pA << " , Address of ClassB object = " << pB << endl;
Now the output that I get is the following:
Address of ClassA object = 0x7fcda0001150 , Address of ClassB object = 0x19f1160
Address of ClassA object = 0x26c77c0 , Address of ClassB object = 0x1aba400
I guess, you just observed that objects are allocated in different memory regions:
Objects with static linkage are generally located in the data segment next to the segment with the program code and typically have relatively small values.
Objects on the stack are typically located at the far end of the memory with the stack normally growing downwards. They have, thus, normally fairly large values.
Objects allocated on the heap are typically somewhere between the data segment and the stack. Depending on how the memory allocation decides to allocate memory, the value are likely to start small, i.e., just above the data segment or fairly large, i.e., just below the stack.
How systems really lay out their memory is entirely up to the system, however. Some systems may have entirely different memory layouts, have stacks growing upwards, etc. Here is a simple program demonstrating this effect:
#include <iostream>
int main()
{
static int a(0);
static int const b(0);
int c(0);
int* d(new int(0));
std::cout << "a=" << &a << '\n'
<< "b=" << &b << '\n'
<< "c=" << &c << '\n'
<< "d=" << d << '\n';
delete d;
}
On my system, this program prints
a=0x103504064
b=0x103503f7c
c=0x7fff5c6fca8c
d=0x7f92204000e0
I guess, something like this difference led you to the assumption that pointers are different but it is just that the value formatted require a different number of digits: all int*s used will have the same size.
Related
I am messing around a little with pointers. Please take a look at the following results (addresses).
1st code:
#include <iostream>
int main(){
int a = 5;
void* pointer = &a;
std::cout << a << std::endl << &a << std::endl;
std::cout << pointer << std::endl ;
std::cin.get();
}
Result:
2nd code:
#include <iostream>
int main(){
int a = 5;
void* pointer = &a;
std::cout << a << std::endl << &a << std::endl;
std::cout << &pointer << std::endl ;
std::cin.get();
}
Result:
Why does the address of the variable a change between the two codes?
In the first case, you never take the address of pointer, so pointer can be stored in a register, or even not at all. (Modern compilers are very clever, and modern machines have many registers.)
For instance, gcc 11 keeps the value in a register without optimization, and with -O2 it just inserts the address of a directly. (Assembly here, for the curious.)
In the second case, you do take the address of pointer, so it must be stored somewhere in memory.
This means that a might be stored in a different place in order to make room for it.
Also, some platforms randomize storage locations in order to make programs less hackable, so it's usually not a good idea to assume that things will have the same address in different "runs".
In the first code poiner stores the address of variable a, and by command.
std::cout<<pointer<<std::endl;
You print the address of a. That's it.
In the second code pointer also stores the address of variable a, but &pointer is the address of variable pointer. Try the following
#include <iostream>
int main(){
int a = 5;
void* pointer = &a;
void** pointer_to_pointer = &pointer;
std::cout << a << std::endl << &a << std::endl << pointer << std::endl;
std::cout << &pointer << std::endl << pointer_to_pointer;
std::cin.get();
}
The output for me is
5
0x7aba1bd92e94
0x7aba1bd92e94
0x7aba1bd92e98
0x7aba1bd92e98
It is very simple.
int a and void* pointer are two distinct variables or I better say memory locations on the stack. a holds a value like 5 in its location. pointer holds the address to a's memory location. pointer itself is stored in a different location and when you write std::cout << &pointer << std::endl; it will print the address of the pointer variable, not the contents of it which is a's address.
As a simplified example:
Consider 0x4 as the address of pointer itself and the value inside it is 0xC. This value points to a's location. In order to read the value of a(which is 5), you first have to go to 0x4 to read its content. Its content is 0xC and now you have successfully found out that a's location is 0xC. Then you have to go to 0xC and at that address, you will find the value 5.
You look at -> 0x4( content == 0xC ) -> 0xC( content == 5 ) -> done!
I can't seem to find the answer on here, but I'm sorry if this is a duplicate. Here's my question: When I have two pointers to the same location, then I change the address of one (let's say pointer A), will I (by accident) be changing the address of the other pointer (pointer B)? Or will pointer B's location stay the same?
Changing the contents of a pointer (as opposed to the object being pointed to) will not affect other pointers to the same object.
Picture speaks a thousand words.
Pointers are pointing to another memory place, at the same time, they have their own memory space.
Two pointers, A and B point to the same place, yet, they are kept in separate memory locations. (Left half of the image)
If you change B, you will only change what B is pointing, A remains the same. (Right half of the image)
Pointer B's location will stay the same.
Because pointer A and pointer B are different pointer,they have different memory address.That means they are independent each other although both of them point to the same memory address.
But you should be careful when you try to change pointer A's content,this operation may cause pointer B be a wild pointer by accident!
A pointer holds the memory address of a piece of data in memory.
The value of the pointer variable is this address.
int targetA = 1;
int targetB = 2;
int *pointerA = &targetA;
int *pointerB = &targetA;
printf("%p, %p\n", pointerA, pointerB);
// => 0x7fff5c78e8f8, 0x7fff5c78e8f8
pointerB = &targetB;
printf("%p, %p\n", pointerA, pointerB);
// => 0x7fff5c78e8f8, 0x7fff5c78e8f4
By assigning a different address / location to the pointer you just change what it points to, other variables are not affeted.
You can see the output of the below code :
#include <iostream>
int main(int argc, char **argv){
int a = 3, d = 4;
int *b = &a, *c = &a;
std::cout << b << ", " << c << std::endl;
b = &d;
std::cout << b << ", " << c << std::endl;
}
The following is the output of the code :
0x7ffca3788e40, 0x7ffca3788e40
0x7ffca3788e44, 0x7ffca3788e40
Clearly, changing the address b points to, has nothing to do with the address pointed by pointer c.
But you can have a near-similar phenomena when you use references. A reference is an entity that is an alias for another object. Suppose you have
int &ref = a;
ref = 5;
Now, changing the variable ref will also bring a change in the value of variable a, equating it to 5.
Let's take a look at this code snippet.
#include <iostream>
#include <string>
using namespace std;
int main ()
{
int * myp1, * myp2;
int myvalue;
myp1 = &myvalue;
myp2 = &myvalue;
myvalue = 10;
cout << "first address is " << myp1 << '\n';
cout << "second address is " << myp2 << '\n';
Here, the outputs are the same (when I run it, I get first address is 0x759ba27bb1d8
second address is 0x759ba27bb1d8).
int myvalue2;
myp1 = &myvalue2;
myvalue2 = 20;
cout << "first address is " << myp1 << '\n';
cout << "second address is " << myp2 << '\n';
return 0;
}
Here, the addresses are different, but myp2 points to the same address as above.
And it makes sense; you have two separate things pointing to the same address. Why would changing what one thing points to change the other?
A (possibly very bad analogy) would be: consider that you and someone on the other end of the world are pointing at the sky (say, at the same point in the sky). Then, you point at the ground. Just because you pointed at the ground, doesn't mean the other guy will stop pointing at the sky.
Hope that helps.
I have created objects by using new, but then have dereferenced them before adding them to a vector. Despite trawling the internet I cannot work out how I can call delete on these items. I want to do this just using standard C++ and STL I don't want (e.g.) to use Boost libraries.
As you can see a, b and c lose scope and I am left with what I presume to be copies in the vector. How can I go about deleting these. I don't want to store pointers in the array as I will need to pass an API function an array of doubles.
Please someone - how do I delete these objects?
#include <iostream>
#include <vector>
using namespace std;
vector<double> vectorDouble;
void createObjects();
void createObjects() {
double* a=new double(13);
double* b=new double(14);
double* c=new double(15);
//a,b and c are not contiguous memory blocks
cout << "memory location of a: " << a << endl;
cout << "memory location of b: " << b << endl;
cout << "memory location of c: " << c << endl;
vectorDouble.push_back(*a);
vectorDouble.push_back(*b);
vectorDouble.push_back(*c);
}
int main() {
createObjects();
//the memory addresses are contiguous 8 byte chunks
cout << "vector memory at 0: " << &(vectorDouble[0]) << endl;
cout << "vector memory at 1: " << &(vectorDouble[1]) << endl;
cout << "vector memory at 2: " << &(vectorDouble[2]) << endl;
//get pointer to the 2nd element
double *P=&(vectorDouble[1]);
//dereference and look inside - two memory locations both contain the value 14
cout << "vector Pointer P ["<< P <<"] contains " << *P <<endl;
//Which should I call delete on? I have lost reference to the original pointers.
//How should I call delete on the vector?
cout << "deleting pointer that references 2nd vector element" << endl;
delete P; //********* CRASH **********
cout << "Done deleting" << endl;
}
The objects you need to delete are not in the vector, because your vector elements are not created with new. You are just passing the copy of the malloc'd doubles, not the actual allocated double to the vector, when you use the dereference operator in the push_back.
You are actually just leaking them - your code would run fine without allocating doubles:
void createObjects() {
vectorDouble.push_back(13);
vectorDouble.push_back(14);
vectorDouble.push_back(15);
}
As everyone points out, there is no reason whatsoever to invoke new in your program:
void createObjects() {
vectorDouble.push_back(13);
vectorDouble.push_back(14);
vectorDouble.push_back(15);
}
Suppose, however, that you do have some reason to call new. (I can't imagine what it might be, but let's assume you are a genius). Here is how you would do that:
void createObjects() {
double* a=new double(13);
double* b=new double(14);
double* c=new double(15);
//a,b and c are not contiguous memory blocks
cout << "memory location of a: " << a << endl;
cout << "memory location of b: " << b << endl;
cout << "memory location of c: " << c << endl;
vectorDouble.push_back(*a);
vectorDouble.push_back(*b);
vectorDouble.push_back(*c);
delete a;
delete b;
delete c;
}
You see, the push_back doesn't put a copy of your pointer in the vector, it puts a copy of your object in the vector. Once you've made the copy of your object, then your object's memory serves no continuing purpose, and can be destroyed.
The function createObjects is not putting the allocated values into the vector; it is putting in the values and then leaking the memory that a, b, and c pointed to. The call:
vectorDouble.push_back(*a);
stores the value pointed to by a in the vector (*a dereferences the pointer, which you probably already know). Once that function returns, the pointers are lost. You cannot retrieve them from the vector. You would either need to make a vector of pointers to doubles or (more likely) don't even allocate values; just store the doubles.
I think I've got the problem, on:
vectorDouble.push_back(*a);
vectorDouble.push_back(*b);
vectorDouble.push_back(*c);
You are passing a, b and c as values so the array don't really contains the variables you have created (that's why they now have different memory address, they are a copy of the content of your variables!). Then you can delete the variables inside the method, don't use pointers inside the method or use an double* vector.
Your leak is in createObjects(), because std::vector<>::push_back() makes a copy of its argument. You should delete the pointer before the end of scope of createObjects().
That said, I don't see why you use dynamic allocation to begin with. If you can avoid that please do (and you can, with a smart pointer like std::unique_ptr<>, or better yet with plain old doubles).
#include <iostream>
int main()
{
int anything[] = {5};
int *something = new int;
*something = 5;
std::cout << &anything << "==" << &anything[0] << "==" << anything << std::endl;
std::cout << &something << "!=" << &something[0] << "==" << something << std::endl;
}
Why is the memory address in &something different from &something[0] and something? Although it is a dynamic allocation, I don't understand why the memory address is different. I tried it with more than one value; it's the same thing. Here I used one value for both for simplicity.
&something is the memory address of the pointer itself (hey, it needs to store that value somewhere!), while &something[0] is the address of the actual memory that is storing your stuff.
something is a pointer. &something is the address of that pointer. &something[0] is the address of the first element pointed to by the pointer, which is completely different from the address of the pointer. something is the value of the pointer, which is also the address of the element that is pointed to.
I'm sure this topic has been covered many times before, I hope I did it justice.
Correction:
I messed up with the concept of pointer address and the address the pointer points to, so the following code has been modified. And now it prints out what I want, variable a, c, i, j, k, p are on the stack, and variable b,d are on the heap. Static and global variables are on another segment. Thanks a lot for all of you!
Well, I know that these two concepts are deeply discussed...but I still have questions for the following code:
#include <iostream>
using namespace std;
class A {
};
int N = 10;
void f(int p) {
int j = 1;
float k = 2.0;
A c;
A* d = new A();
static int l = 23;
static int m = 24;
cout << "&c: " << &c << endl;
cout << "&d: " << d << endl;
cout << "&j: " << &j << endl;
cout << "&k: " << &k << endl;
cout << "&l: " << &l << endl;
cout << "&m: " << &m << endl;
cout << "&p: " << &p << endl;
}
int main() {
int i = 0;
A* a;
A* b = new A();
cout << "&a: " << &a << endl;
cout << "&b: " << b << endl;
cout << "&i: " << &i << endl;
cout << "&N: " << &N << endl;
f(10);
return 0;
}
My result is:
&a: 0x28ff20
&b: 0x7c2990
&i: 0x28ff1c
&N: 0x443000
&c: 0x28fef3
&d: 0x7c0f00
&j: 0x28feec
&k: 0x28fee8
&l: 0x443004
&m: 0x443008
&p: 0x28ff00
This is pretty interesting, coz except the global variable N, and two static variables in function f, which are l and m, the addresses of all the other variables seem to be together. (Note: The code and the results have been modified and not corresponding to what is said here.)
I've searched a lot about stack and heap. The common sense is that, if an object is created by "new", then it is on the heap. And local variables (such as j and k in the above sample) are on stack. But it seems not to be the case in my example. Does it depend on different compilers, or my understanding is wrong?
Thanks a lot for all of you.
Your understanding is wrong. For example, b is a pointer - if you want the address of the object created by new, you need to print out b, not &b. b is a local variable, so it itself (found at &b) is on the stack.
For your example, N, l, and m are presumably somewhere in your executable's data section. As you can see, they have similar addresses. Every other variable you are printing out is on the stack - their addresses are likewise similar to one another. Some of them are pointers pointing to objects allocated from the heap, but none of your printouts would show that.
Your understanding is correct.
local variables are allocated on the stack.
dynamically allocated objects are allocated on the heap.
Though you are taking the address of the local variable consistently in your example.
Example: print out d not the address of d. As d is a local variable (so the address is similar to c) but it is a pointer variable that points at a dynamically allocated object (that is on the heap).
How the compiler implements the stack and heap though will vary.
In modern OS the stack and heap may even share the same area (ie you can implement the stack by allocating chunks in the heap).
If you want to print the address of whatever d points to (in this case it points to an object on the heap), do
cout << "d: " << d << endl;
That will print the value of the pointer, and the value of a pointer is the address of the object it points to.
Your code had
cout << "&d: " << &d << endl;
This prints the address of d , as you defined d inside main, it'll be on the stack, you're printing the address of your pointer. There's the pointer itself, and the object it points to, they're 2 seperate things, with seperate addresses.
The only ones that are not 'together' in your example are l, m and N. They are two statics and one global, therefore they are not allocated on the stack for sure. They aren't from a heap neither, most likely, they are from a .data segment of your module. The only one from a heap should be the address b points to, but you're printing the address of b itself, not what it points to.
The distinction between the two forms, from a pure C++ perspective, is only to do with how lifetime of objects are managed.
From here, good read
Static variables are in the data segment. Also you mix the address of a pointer and it value. For example a:
a is a local variable of type A* on the stack. &a also gives the address where a actaully resieds (on the stack). The value of a is an address of a heap object of type A;
You can't depend on various compilers doing things the same way. For almost every bit of code you will write the distinction between stack and heap are meaningless. Don't worry about it.
One may not safely assume anything about the relative addresses of things in the stack relative to those on the heap nor, for that matter, the relative addresses of any pointers that are not all derived from the same array or allocated (via malloc, calloc, etc.) block. I'm not even sure pointers are required to be rankable.