I am playing around with boost scoped pointers and I don't understand this behaviour:
#include <iostream>
#include <boost/scoped_ptr.hpp>
int main()
{
boost::scoped_ptr<int> p{new int{1}};
std::cout << &p << '\n';
p.reset(new int {2});
std::cout << &p << '\n';
return 0;
}
I get the following output:
0x7fff5fbff650
0x7fff5fbff650
Shouldn't the reset function change the address pointed by p?
this is the case if use a scoped array instead of a scoped pointer and print the address pointed by the first element in the code above.
When you do
std::cout << &p << '\n';
you are getting the address of p, not what p points to. To get that you need
std::cout << static_cast<void*>(p.get()) << '\n';
The static_cast<void*>() is not really needed in this example as printing a pointer, other than a char*/const char* will give you its address but I added it to just be safe.
You're taking the address of the scoped_ptr called p. There's only one of them!
If you'd printed &*p or p.get() instead (though prefer (void*)p.get() for sanity) then you'd be printing the address of the thing it currently points to.
This address will always change, because you create the second object (using new) slightly before the first one is destroyed, and objects cannot share addresses.
If you'd done a .reset() first, though, then you may or may not see this address changing, depending on what the innards of new did; objects don't have to have addresses unique to the lifetime of your program, as long as they don't share the address of another object that still exists! However, even then, in practice, to be honest, I'd be surprised if the second dynamically-allocated int wound up at the same address as the first.
You are printing address of object p with is a boost::scoped_ptr.
You should use p.get() to get address of handle object;
Related
Hello guys) I would love to get an answer for this question:
Let me share a small portion of code I have written in C++:
#include <iostream>
using namespace std;
int main() {
int* ptr;
int var = 7;
ptr = &var;
cout << "var address:" << &var << endl;
int &ref = var;
cout << "ref address:" << &ref << endl;
cout << "Var value: " << var << endl;
cout << "ref value: " << ref << endl;
return 0;
}
after writing this block of code, I've realized that the addresses that store the variables var and ref are equal. The values these two variables store are the same too. However, I just don't get it in terms of actual numbers of variables the OS memory has allocated for: did the OS allocate memory for ref and var separately or did it allocate only 1 spot in memory for these two(var and ref) variables (if so, does it mean that the spot in memory has two names/identifiers (ref and var)?
I have tried to understand what is actually going on in memory and how does it allocate memory. I wanted to know also how the memory system is actually designed since I cannot comprehend this problem just by drawing box/pointer diagrams.
References are not objects and don't have all the basic properties of object such as storage or size. There may be no storage to get an address to. If you try to get the address or size of a reference, you will instead get the address of the referred object or the size of the referred object.
From https://en.cppreference.com/w/cpp/language/reference :
References are not objects; they do not necessarily occupy storage, although the compiler may allocate storage if it is necessary to implement the desired semantics
So a reference might occupy addressable storage, but only when the implementation needs that storage to implement reference semantics (such as by using a pointer in the background). But this is an implementation detail. It is mostly hidden from the developer, and even then trying to get its address will still give a pointer to the referred object instead.
Note that pointers are objects. They occupy storage, have a size and their address can be obtained with &, just like an int. This is why you observe different behavior with references and with pointers.
In general, references are glorified pointers, that auto-deference on use, can't be changed to point to a different object after being created, and aren't allowed to be null.
In simple cases like this one, the reference will almost surely be optimized away, and every access to ref will be replaced directly with var.
But in general case, they occupy storage like pointers, though you can't easily get the address of that storage, because applying & to a reference returns the address of the target object.
Using pointers in the example below gave me a confusion so I probably misunderstand something. I will try to show my way of understanding and some pseudo-simple example.
Creating std::unique_ptr variable of name my_int ensures that it can not be copied and there is only one owner of it's int object. Then I create a vector to storage the pointer and put it without copying with std::emplace_back().
Now I would like to check if the element of vector integers[0] has the same address in memory as the orginal element my_int. I thought it should because this element could not be copied.
Example code:
auto my_int = std::make_unique<int>(1);
std::vector<std::unique_ptr<int>> integers;
integers.emplace_back(my_int.get());
std::cout<< "Value of my_int: " << *my_int << std::endl;
std::cout << "Address of my_int: " << my_int.get() << std::endl;
std::cout << "Also address of my_int: " << &my_int << std::endl;
std::cout << "Also address of my_int: " << &integers[0]<< std::endl;
std::cout << "Also address of my_int: " << integers[0].get()<< std::endl;
Result of test:
Value of my_int: 1
Address of my_int: 0x260fc40
Also address of my_int: 0x65fb58
Also address of my_int: 0x260fe20
Also address of my_int: 0x260fc40
I also tried using std::move() when putting the object to vector but the effect is the same, addresses differs but I don't understand why.
My first confusion is that &my_int and my_int.get() is not the same and the second confusion is that also integers[0].get() differs from &integers[0].
The expression my_int.get() returns a pointer to the contained integer, its type is int*.
The expression &my_int returns a pointer to the my_int object itself, and has the type std::unique_ptr<int>*.
And integers[0] is a distinct and different object from my_int. They just happen to contain the same pointer. This is bad for a unique pointer: together, they will try to free the same memory twice. You must use std::move
auto my_int = std::make_unique<int>(1);
std::vector<std::unique_ptr<int>> integers;
integers.emplace_back(std::move(my_int)); // push_back also works
This way my_int will be set to contain nullptr, and only integers[0] will contain the pointer to the allocated memory.
To understand my_int (or pointers in general really) better you might think of it something like this:
+--------+ +---+
| my_int | --> | 1 |
+--------+ +---+
^ ^
| |
&my_int my_int.get()
It's the same thing with integers[0].get() and &integers[0].
Creating std::unique_ptr variable of name my_int ensures that it can not be copied and there is only one owner of it's int object.
It is only the std::unique_ptr that cannot be copied. But unique pointer cannot guarantee that you won't copy the bare pointer that it owns. Copying the bare pointer owned by the unique pointer is what exactly you did which results in two "unique" owners of the same resource. And that will result in undefined behaviour when the second unique pointer is destroyed.
When you call std::unique_ptr::get, the unique pointer won't release its ownership to you. You should never pass a pointer, that isn't owned by you, into constructor of a smart pointer.
To fix this, you can transfer the ownership from one smart pointer into another by move:
integers.emplace_back(std::move(my_int));
addresses differs but I don't understand why.
The unique pointer variable is one object, and the element of the vector is another object. Since they are separate objects, they have a separate address. Even if they happen to be pointers that point to the same object - the integer, which is yet another object. Those three objects correspond to the three different addresses that you see in the output.
The difference between smart pointers and raw pointers has been discussed before (e.g. When should I use raw pointers over smart pointers?), but I can't quite get the answer to this question from the material I have been reading the last day or so.
I have a class A that has a pointer int* a to some data. In the context I am thinking about, the value that a points to might be used somewhere else in the program so A does not have ownership over a, it just refers to it. For example, a house exists (e.g. int h) and a person (i.e. class) has a reference to their house (e.g. int* my_h).
The first way I handled this was without using smart pointers, but I am curious about the benefits of using smart pointers in this example. I suspect there are not many because ownership really isn't much of an issue and I am not calling new and delete.
The example with raw pointers:
#include<iostream>
class A{
public:
A(int a_val){
std::cout << "Creating A instance ";
a = &a_val;
std::cout << "with a = " << *a << std::endl;
};
private:
int* a;
};
int main()
{
int x = 5;
std::cout << "x is " << x << std::endl;
A a(x);
return 0;
}
Here, a has the raw pointer int* a, which is assigned to &x in main().
The example with smart pointers (a unique_ptr):
#include<memory>
#include<iostream>
class A{
public:
A(std::unique_ptr<int> a_val){
std::cout << "Creating A instance ";
a = std::move(a_val);
std::cout << "with a = " << *a << std::endl;
};
private:
std::unique_ptr<int> a;
};
int main()
{
std::unique_ptr<int> x = std::make_unique<int> (5);//int x = 5;
std::cout << "x is " << *x << std::endl;
A a(std::move(x));
return 0;
}
The use of unique_ptr seems overkill here to me, and doesn't benefit readability or performance. Is that correct?
EDIT
As pointed out (...) in the comments, there were a number of problems with the original example. The raw pointer example should be:
#include<iostream>
class A{
public:
A(int* a_val){
std::cout << "Creating A instance ";
a = a_val;
std::cout << "with a = " << *a << std::endl;
};
private:
int* a;
};
int main()
{
int x = 5;
std::cout << "x is " << x << std::endl;
A a(&x);
return 0;
}
and the smart pointer example should perhaps use a shared_ptr.
To be more specific, I am interested in cases where this scales up to large numbers of instances of classes, which have pointers (or vectors of pointers) to data structures defined elsewhere. For instance, in agent based models, agents sometimes need to 'find' another agent, and thus a vector of pointers could (in my understanding) be used to refer to which other agents one particular agents should 'know about'. The agents themselves will be created outside of the agent class.
As was pointed out by #YKsisarvinen in a comment,
One difference is that your raw pointer version doesn't work. You assign a pointer to a temporary variable, which dies as soon as constructor is done. Which highlights a very important difference between raw and smart pointers - smart pointers prevent you from most of such mistakes.
One possible approach is to store a reference to the object that is owned by somebody else.
struct A
{
A(int& a_val) : a(a_val) {}
int& a;
};
However, that would prevent you from being able to assign objects.
int i = 10;
int j = 20;
A a1(i);
A a2(j);
a1 = a2; // This will be an error.
You can use std::reference_wrapper to overcome that barrier.
struct A
{
A(int& a_val) : a(a_val) {}
std::refernce_wrapper<int> a;
};
I am curious about the benefits of using smart pointers in this example
Depends on the smart pointer you are talking about:
unique_ptr: you cannot use this one for your use case, because that implies you own the object.
shared_ptr: this would work, but you would need to use shared_ptr everywhere and you would tie its lifetime to your class.
weak_ptr: same as above, but this would not tie the lifetime (it can be destroyed by others meanwhile).
Some other non-standard smart pointer: depends.
In general: if you only need to keep a reference to an object, use a reference or a pointer. Of course, you will have to ensure the reference/pointer remains valid, which can be trivial or a nightmare, depending on the design of your program.
The main question is: who's owning the pointer. In this example:
int main()
{
std::unique_ptr<int> x = std::make_unique<int> (5);//int x = 5;
std::cout << "x is " << *x << std::endl;
A a(std::move(x));
return 0;
}
It's just the same.
But if you do something like:
A funct(int n)
{
std::unique_ptr<int> x = std::make_unique<int> (n);
std::cout << "x is " << *x << std::endl;
A a(x.get());
return a;
}
Then you NEED to transfer the ownership, because as soon as you leave funct, x goes out of scope and gets destroyed. And the A object that you return now points to garbage. So you'll do:
A funct(int n)
{
std::unique_ptr<int> x = std::make_unique<int> (n);
std::cout << "x is " << *x << std::endl;
return A(std::move(x));
}
So, the A returned now owns the pointer and will destroy it when itself gets destroyed.
Even before jumping into the benefits of Smart Pointers, I would recommend understanding why are they even needed. First and foremost, smart pointers were never meant to replace the use of all Raw pointers. They were designed with a very very specific purpose: Memory management i.e. cleaning up/freeing dynamically allocated memory.
Now lets say we have a simple function as follows:
1. void func()
2. {
3. SomeResource* raw_sr = new SomeResource(); //--->Memory allocated here.
4. .
5. .
6. if(someCondition==false)
7. return;
8.
9. delete raw_sr;
10. return;
11.}
The above function can terminate in 2 ways:
1. Returning from Line 10. -->Normal termination
2. Returning from Line 7. -->Termination under some error condition
In the first situation we cleaned up the memory.
But for situation 2, we have a potential memory leak as we did not free the raw_sr.
So apparently, there is only one place where the memory was not deleted.
We can add an explicit code there to free up the raw_sr memory.
But the point is, there can be a number of situations in the code, where this can happen and forget to free up the memory. It can also be while handling exceptions.
But what if, under all terminating conditions we are guaranteed that the memory will be freed up ?
There is only one function that is called under all such circumstances: the destructor of a static object.(Not dynamic - very imp.)
So the idea is to give the responsibility of holding a pointer to a specific class whose job will be to free up the memory held by the pointer when its destructor is called.
This class is called a Smart Pointer.
So now your code would look like this:
1. void func()
2. {
3. SmartPointer<SomeResource> smart_sr(new SomeResource()); //--->Memory allocated here
4. . // but passed onto the smart_sr obj.
5. .
6. if(someCondition==false)
7. return;
8.
9. return;
10.}
Now under all circumstances, be it on line no 7 or 10, the destructor of smart_sr will be called and that will free up the memory held for SomeResource.
This is the primary and fundamental understanding of a Smart Pointer.
Hence, usage of a smart pointer depends on its usage context.
Now based n your example, Class A represents a Person that holds int* my_house.
Now lets say you are not the only person staying in this house. You are staying with your wife.
From a logical perspective your object and your wife's object should point to the same House pointer.
So your object alone CANNOT be the owner of this house's pointer. Because then your Wife's object wont be able to refer to it.
So std::unique_ptr cannot be used for holding the house pointer.
Well you guys share the home ..right ?
Hence, std::shared_ptr, will make sense.
Now lets say, your wife left, the home(for some reason) so she gives up the pointer. Will the house be returned back to its owner ? No. You are still staying there. Subsequently, you move out too after a few days, then you too will give up this pointer. And because you were the last person staying in it, the memory holding this house will finally be freed.
Hope this clears your doubt and puts you in the right direction to understanding smart pointers.
in the following code I found that same pointer instruction crash the application in a situation while not in other situation.
#include <iostream>
using namespace std;
int main()
{
int *p;
*p = 50; //this instruction causes the crash
int* q = new int;
*q = 50; //this instruction executes ok
cout << "p:" << p << endl;
cout << "q:" << q << endl;
return 0;
}
I want to know why this is the case?
The first pointer is uninitialized. It doesn't point to a memory location that has an int value. So when you deref it on the next line, you get a crash.
The second pointer is initialized to an int that has an actual space in memory. So when you deref it, it finds the value held in that space.
int *p;
This pointer points to nowhere i.e not at any valid address of the process. That's why it crashes
int* q = new int;
Points to a valid address returned by new int, hence worked
I see you need some links to documentation:
http://en.cppreference.com/w/cpp/language/pointer
http://en.cppreference.com/w/cpp/language/operator_member_access
http://en.cppreference.com/w/cpp/language/new
http://en.cppreference.com/w/cpp/language/delete
http://en.cppreference.com/w/cpp/language/storage_duration
To wrap it up:
You can use the indirection operator (*) to return the object the pointer points to (dereference the pointer).
You can only access (read or modify) an object via a pointer, when the pointer actually points to an object (which by default they don't).
You can assign the address of an object to the pointer to let the pointer point at it.
You can use the address-of operator (&) to acquire the address of an object for assigning it to a pointer.
You can use the new operator to create a new object and return the address to it for assigning it to a pointer.
You must use delete to eventually destroy objects created using new.
When you use pointers, you alone are responsible for the validity of the objects your pointers point to. Don't expect the compiler to warn you when objects are leaked or accessed beyond the end of their lifetime. If you do it wrong, you might observe undefined behavior.
Smart pointers can help to keep track of object ownership and take care of proper destruction.
For further reading:
Can a local variable's memory be accessed outside its scope?
What does "dereferencing" a pointer mean?
Undefined, unspecified and implementation-defined behavior
What is a smart pointer and when should I use one?
https://ericlavesson.blogspot.de/2013/03/c-ownership-semantics.html
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#e6-use-raii-to-prevent-leaks
#include <list>
#include <iostream>
struct Foo
{
Foo(int a):m_a(a)
{}
~Foo()
{
std::cout << "Foo destructor" << std::endl;
}
int m_a;
};
int main( )
{
std::list<Foo> a;
Foo b(10);
std::cout << &b << std::endl;
a.push_back(b);
Foo* c = &(*a.begin());
std::cout << c << std::endl;
a.erase(a.begin());
std::cout << a.size() << std::endl;
c->m_a = 20;
std::cout << c->m_a << std::endl;
std::cout << b.m_a << std::endl;
}
The result is:
0x7fff9920ee70
0x1036020
Foo destructor
0
20
10
Foo destructor
I usually think after i erase an object in a list i can't access member variable of thar object any more. But in the above I can still access c->m_a after I have erased the object what c points to,Why?
with Foo* c = &(*a.begin()); you have created a pointer to an object which you intentionally destroy (via the erase()). However the memory for the object for is still there (since this is a very simple application, and the OS did not claim it for something else).
So you effectively use memory which is not yours anymore to use.
Well, data integrity is only guaranteed as long as you have allocated that part of the memory (whether by it on the stack or on the heap using new/malloc).
What happens with your data once you have freed it, is undefined (meaning it is implementation dependent). The most efficient way of freeing memory is by simply marking the memory as being available, leaving your data there until another program claims that part of the memory using malloc and overwrites it. This is how most implementations will handle this.
C++ does not check whether the data you are reading or writing belongs to your program. That is why you get a segmentation fault when your program tries to write data to a place in the memory it does not have access to.
In your case you will free the memory and then you check for its value immediately. C++ will happily execute your code. Since you only freed it recently, the odds are very high that your data is still there (but certainly not guaranteed: sooner or later it will get overwritten).
Welcome to the wild world of pointers. What exactly you got here is case of Dangling Pointer (Read up the wiki article, it explains it in detail).
Basically what happened here is that after removing the item from the list, the pointer c became dangling pointer (it is pointer to a memory location which is no more occupied by Foo object). But still C++ will allow you to read/write through this pointer, but the side affects will be totally non deterministic (means anything can happen). As the code is simple s during testing your code you just got lucky (or unlucky as these type of problems can become very difficult and dangerous as they get old).