I've been playing around with a way to handle function-objects and I'm curious about if I'm misunderstanding something, possibly creating a problem further down the line. I ask, because I want to see this approach work, and understand better what I'm doing.
The idea is quite simple: I create a virtual access pointer like this:
struct access { virtual void tick() = 0; };
The obj (out of many different) the access pointer will work on:
struct obj1 :public access
{ void tick() { cout << "I'm being called " << endl; } };
And I have the "controller" class that will (eventually) hold and control the flow of the actions:
class container
{
vector<access*>acc_objects; //do these exists by themselves?
public:
void obj_add(access &x) { acc_objects.push_back(&x); }
void tick() { for (auto x : acc_objects)x->tick(); } //active functors
}controller; //there will be only 1
The goal (eventually) will be to send a pointer to various objects, to a vector of access pointers, thereby being able to call them as if they were the same. Either way, whats confusing me at this point is when I do this:
{ //in scope
obj1 anobj;
conts.obj_add(anobj);
int x=1; //x in scope
}
conts.tick(); //referrign to the object still works
cout<<x<<endl; //but this does not
Why can I still refer to obj1? Is this just undefined behaviour, or does the object exist by reference only somehow. Im also asking, because finding a way to have functor-objects exist and vanish reliably is something I'm trying to accomplish.
Edit: cleaned up the question, took out some irrelevant code from the example
Your bug is not object slicing per se.
{
obj1 anobj;
// ...
}
Here, anobj goes out of scope, and gets destroyed at the end of the scope.
Meanwhile, inside the scope, a pointer to anobj gets saved in your container. Referencing the object via the pointer, after the scope has ended results in a reference to a destroyed object.
Nothing was sliced anywhere. The entire object was destroyed, and the subsequent reference to the object comprises undefined behavior.
Related
I have a situation where I have a piece of hardware and it really only makes sense for a single connection to be open on that hardware at the same time, so I really only want to refer to one object no matter where it's passed. So it may look something like:
class Hardware {
public:
void Open(); //this will create and launch a connection monitor in the background
void Close();
std::string SendPing();
std::string AskForSomeOtherData();
bool isConnected();
bool setConnected(bool connState);
private:
bool connected_;
int hndl_;
}
I then have another class monitoring the connection in the background so my UI can be notified if a connection is lost.
class ConnectionMonitor{
ConnectionMonitor(Hardware& hw);
void Run(); //launches a background thread to send "pings" to the device to make sure it's there. Will update Hardware.connected_
Hardware hw_; //or Hardware* hw_, or shared_ptr<Hardware> hw_, or Hardware& hw_;
}
When the connection monitor notices a connection is lost, it needs to update the connected boolean of the hardware object passed in directly, because my other threads using the object will also want to know it's been disconnected. But I don't know if updating the private data of the object indicates ownership of the object itself?
I don't believe so, since the lifetime of the object shouldn't be effected. There are all these different ways to pass an object shared between two classes, but I don't know what the problem domain calls for when I need to store it in class private data. Requiring a shared pointer to be passed in is one option. But I am not really indicating any ownership of the object being taken I don't think? A reference seems to be more fitting possibly, but then I end up with needing Hardware& hw; in my ConnectionMonitor private data so I keep a reference to the Hardware object. Then I read stuff that says "Reference in private data bad."
Also, if the caller is storing the hardware object as a shared_ptr, I believe I would have to do something like the following to pass it into my ConnectionMonitor:
ConnectionMonitor(*hardware);
but is this ok for a shared pointer, to dereference it, pass the object to a constructor, and then have the consuming class store another pointer to the same object that the shared pointer owns?
ConnectionMonitor(Hardware& hw){
Hardware* = hw; //not 100% sure if this syntax is correct, still learning. Most importantly here I'd be taking the hw object being referenced and pointing at it internally, rather than creating a copy
}
It seems now I am now creating a pointer to an object that the shared pointer already owns.
There are a lot of questions embedded above in what amounts to be a brain dump on my thought process, so I will try to summarize. When two threads need access to the same resource, and that resource needs to be updated from either thread, is this a case for a shared pointer? If one of the classes is not taking ownership, what is the best way to store that shared object in private data?
but is this ok for a shared pointer, to dereference it, pass the object to a constructor, and then have the consuming class store another pointer to the same object that the shared pointer owns?
Yes raw pointers are fine when the are non-owning. You can use std::shared_ptr::get to retrieve the stored raw pointer. However, when you store the raw pointer you need to consider the lifetime of the object. For example this is fine:
#include <memory>
#include <iostream>
struct bar {
std::shared_ptr<int> owning_ptr;
bar() : owning_ptr(std::make_shared<int>(42)) {}
~bar() { std::cout << "bar destructor\n"; }
};
struct foo {
int* non_owning_ptr;
~foo() { std::cout << "foo destructor\n"; }
};
struct foobar {
bar b;
foo f;
foobar() : b(),f{b.owning_ptr.get()} {}
};
int main() {
foobar fb;
}
b gets initialized first and f can use a pointer to the int managed by owning_ptr. Because f gets destroyed first, there is no danger of f using non_owning_ptr after owning_ptr already deleted the int.
However, only in certain circumstances you can be certain that the raw pointer can only be used as long as the object managed by a smart pointer is alive. As mentioned in a comment, the non-owning counter part to std::shared_ptr is std::weak_ptr. It does not increment the reference count, hence does not prevent the managed object to be deleted when all std::shared_ptrs to the object are gone.
#include <memory>
#include <iostream>
struct moo {
std::weak_ptr<int> weak;
void do_something() {
std::shared_ptr<int> ptr = weak.lock();
if (ptr) { std::cout << "the int is still alive: " << *ptr << "\n"; }
else { std::cout << "the int is already gone\n"; }
}
};
int main() {
moo m;
{
std::shared_ptr<int> soon_gone = std::make_shared<int>(42);
m.weak = soon_gone;
m.do_something();
}
m.do_something();
}
Output is:
the int is still alive: 42
the int is already gone
As already mentioned the std::weak_ptr does not keep the object alive. Though, it has a lock method that locks the object from being destroyed as long as the returned std::shared_ptr is alive. When lock is called on the weak_ptr when the object is already gone, also the returned shared pointer is empty.
When two threads need access to the same resource, and that resource needs to be updated from either thread, is this a case for a shared pointer?
Yes and no. The ref counting of std::shared_ptr is thread safe. Though using a shared pointer does not automagically make the pointee thread safe. You need some synchronization mechanism to avoid data races.
The code I'm currently working on had it's own RefPtr implementation which was failing at random.
I suspect that this could be a classic data race. RefPtr has a pointer to original object that inherits from the RefCounted class. This class contains a reference counter (m_refCount) that is not atomic and an application was crashing inside some threadwork accessing object through RefPtr stuff. Just like the object under RefPtr got destroyed. Quite impossible.
The object instance that is held by RefPtr is also held by two other objects that do not modify it (or its contents) and I'm 100% sure that they have shared ownership of it (so m_refCount should never go below 2)
I did try to replace the pointer with std::shared_ptr, but the crash is still there.
The distilled code representing this issue:
class SharedObjectA
{
public:
int a;
}
class Owner
{
public:
shared_ptr<SharedObjectA> objectA;
}
class SecondOwner
{
shared_ptr<SharedObjectA> objcectA;
public:
shared_ptr<SharedObjectA> GetSharedObject() { return objectA;}
void SetSharedObject(shared_ptr<SharedObjectA> objA) { objectA = objA;}
}
void doSomethingThatTakesTime(SecondOwnerA* owner)
{
sleep(1000+rand()%1000);
shared_ptr<SharedObjectA> anObject = owner->GetSharedObject();
int value = anObject.a;
std::cout << " says: " << value;
}
int main()
{
Owner ownerA;
ownerA.objectA.reset(new SharedObjectA());
SecondOwner secondOwner;
secondOwner.SetSharedObject(ownerA.objectA);
//objectA instance
while(true)
{
for(int i=0;i<4;i++)
{
std::thread tr(doSomethingThatTakesTime,secondOwner);
}
sleep(4*1000);
}
}
What's happening is up to 4 threads access SharedObject using GetSharedObject and do something with it.
However, after giving it some time - the use_count() of shared_ptr will go down below 2 (it should not) and eventually below 1 so the object(objectA) will get destroyed.
Edit
Obviously there is no synchronization in this code. However i don't see how this could be related to the fact the use_count() getting below 2. the shared_ptr is guaranteed to be thread safe for the sake of reference counting, isn't it?
You don't have any kind of synchronization on access to the shared object. shared_ptr does not do any synchronization in access to the pointed-to object, it just ensures that the memory pointed to gets released after all references to it are destroyed.
You also need to join() your threads at some point.
This is not a question about why you would write code like this, but more as a question about how a method is executed in relation to the object it is tied to.
If I have a struct like:
struct F
{
// some member variables
void doSomething(std::vector<F>& vec)
{
// do some stuff
vec.push_back(F());
// do some more stuff
}
}
And I use it like this:
std::vector<F>(10) vec;
vec[0].doSomething(vec);
What happens if the push_back(...) in doSomething(...) causes the vector to expand? This means that vec[0] would be copied then deleted in the middle of executing its method. This would be no good.
Could someone explain what exactly happens here?
Does the program instantly crash? Does the method just try to operate on data that doesn't exist?
Does the method operate "orphaned" of its object until it runs into a problem like changing the object's state?
I'm interested in how a method call is related to the associated object.
Yes, it's bad. It's possible for your object to be copied (or moved in C++11 if the distinction is relevant to your code) while your are inside doSomething(). So after the push_back() returns, the this pointer may no longer point to the location of your object. For the specific case of vector::push_back(), it's possible that the memory pointed to by this has been freed and the data copied to a new array somewhere else. For other containers (list, for example) that leave their elements in place, this is (probably) not going to cause problems at all.
In practice, it's unlikely that your code is going to crash immediately. The most likely circumstance is a write to free memory and a silent corruption of the state of your F object. You can use tools like valgrind to detect this kind of behavior.
But basically you have the right idea: don't do this, it's not safe.
Could someone explain what exactly happens here?
Yes. If you access the object, after a push_back, resize or insert has reallocated the vector's contents, it's undefined behavior, meaning what actually happens is up to your compiler, your OS, what do some more stuff is and maybe a number of other factors like maybe phase of the moon, air humidity in some distant location,... you name it ;-)
In short, this is (indirectly via the std::vector implemenation) calling the destructor of the object itself, so the lifetime of the object has ended. Further, the memory previously occupied by the object has been released by the vector's allocator. Therefore the use the object's nonstatic members results in undefined behavior, because the this pointer passed to the function does not point to an object any more. You can however access/call static members of the class:
struct F
{
static int i;
static int foo();
double d;
void bar();
// some member variables
void doSomething(std::vector<F>& vec)
{
vec.push_back(F());
int n = foo(); //OK
i += n; //OK
std::cout << d << '\n'; //UB - will most likely crash with access violation
bar(); //UB - what actually happens depends on the
// implementation of bar
}
}
I know that it's possible to say delete this in C++ whenever you allocated something with new, using traditional pointers. In fact, I also know that it's good practice IF you handle it carefully. Can I have an object say delete this if it's being held by an std::shared_ptr? And that ought to call the destructor, right? To give you an idea, I'm making a game where a ship can shoot missiles, and I'd like to have the missiles delete themselves.
No, it's not safe, the lifetime of the object is determined by holders of shared_ptr, so the object itself cannot decide whether it wants to die or not. If you do that, you'll get double
delete when last shared_ptr dies. The only solution I can offer is "rethink your design" (you probably don't need shared_ptr in the first place, and missiles probably could be values or pooled objects).
For a missile to delete itself it must own itself, or at the very least, share ownership of itself with others. Since you say that there is a shared_ptr to the missile, I am assuming that you already have multiple objects sharing ownership of the missile.
It is possible for the missile to hold a shared_ptr to itself, and thus share in the ownership of itself. However this will always create a cyclic ownership pattern: For as long as the missile's shared_ptr data member refers to itself, the reference count can never drop to zero, and thus the missile is leaked.
You could have an external object or event tell the missile to delete itself but then I'm not sure what the point is. In order to tell the missile to delete itself, that communication should take place via a shared_ptr, and then the delete isn't really going to happen until that shared_ptr lets go of the missile.
Yes, it is possible. No, I don't think it is a good idea. It looks prone to memory leakage to me and doesn't actually add value. But for the curious, here is how you would do it:
#include <iostream>
#include <memory>
class missile
: public std::enable_shared_from_this<missile>
{
std::shared_ptr<missile> self_;
public:
missile()
{}
~missile() {std::cout << "~missile()\n";}
void set_yourself()
{
self_ = shared_from_this();
}
void delete_yourself()
{
if (self_)
self_.reset();
}
};
int main()
{
try
{
std::shared_ptr<missile> m = std::make_shared<missile>();
m->set_yourself();
std::weak_ptr<missile> wp = m;
std::cout << "before first reset()\n";
m.reset();
std::cout << "after first reset()\n";
// missile leaked here
m = wp.lock();
m->delete_yourself();
std::cout << "before second reset()\n";
m.reset(); // missile deleted here
std::cout << "after second reset()\n";
}
catch (const std::exception& e)
{
std::cout << e.what() << '\n';
}
}
I know I'm late to the show but I ran into wanting to do this myself just now and realized that it is "kind-of-possible" but you need to take care of a few things.
Howard's answer is on the right track but misses the mark as you shouldn't leave construction of the original shared_ptr to the client. This is what opens up the risk of memory leaks. Instead you should encapsulate the construction and only allow weak pointers.
Here is an example:
class Missile{
private:
Missile(...){ }; // No external construction allowed
Missile(const Missile&) = delete; // Copying not allowed
void operator = (const Missile&) = delete; // -||-
std::shared_ptr<Missile> m_self;
public:
template<typename... Args>
static MissilePtr makeMissile(Args... args){
auto that = std::make_shared<Misile>(args...);
that.m_self = that; // that holds a reference to itself (ref count = 2)
return that; // 'that' is destroyed and ref-count reaches 1.
}
void die(){
m_self.reset();
}
...
};
typedef std::weak_ptr<Missile> MissilePtr;
void useMissile(MissilePtr ptr){
auto missile = ptr.lock(); // Now ptr cannot be deleted until missile goes out of scope
missile->die(); // m_self looses the reference but 'missile' still holds a reference
missile->whatever(); // Completely valid. Will not invoke UB
} // Exiting the scope will make the data in missile be deleted.
Calling die() will result in semantically the same effect as delete this with the added benefit that all MissilePtr that are referring to the deleted object will be expired. Also if any of the MissilePtr are used for accessing this then the deletion will be delayed until the temporary std::shared_ptr used for the access is destroyed saving you life-time headaches.
However you must make sure that you always keep at least one MissilePtr around and at some point call die() otherwise you will end up with a memory leak. Just like you would with a normal pointer.
This question is quite old, but I had a similar issue (in this case a "listener" object that had to manage its own lifecycle while still being able to share weak pointers), and googling around did not provide a solution for me, so I am sharing the solution I found, assuming that:
The object manages it's own lifecycle, and hence will never share a
share_ptr, but a weak_ptr (if you need shared_ptr's a similar
solution + use_shared_from_this could do it).
It is a bad idea to break RAII, and hence we will not do it: what we
adress here is the issue of having a shared_ptr owned by an object
itself, as containing a member share_ptr leads to double call to
the object destruction and normally a crash (or at least undefined
behaviour), as the destructor is called twice (once at normal
object destruction and a second one when destroying the self
contained shared_ptr member).
Code:
#include <memory>
#include <stdio.h>
using std::shared_ptr;
using std::weak_ptr;
class A {
struct D {
bool deleted = false;
void operator()(A *p) {
printf("[deleter (%s)]\n", p, deleted ? "ignored":"deleted");
if(!deleted) delete p;
}
};
public: shared_ptr<A> $ptr = shared_ptr<A>(this, D());
public: ~A() {
std::get_deleter<A::D>($ptr)->deleted = true;
}
public: weak_ptr<A> ptr() { return $ptr; }
};
void test() {
A a;
printf("count: %d\n", a.ptr().lock().use_count());
printf("count: %d\n", a.ptr().use_count());
}
int main(int argc, char *argv[]) {
puts("+++ main");
test();
puts("--- main");
}
Output:
$ g++ -std=c++11 -o test test.cpp && ./test
+++ main
count: 2
count: 1
[deleter (ignored)]
--- main
The shared_ptr deleter should never get called for an object allocated in stack, so when it does at normal object destruction, it just bypasses the delete (we got to this point because the default object destructor was already called).
I'm not new to programming, but after working in Java I'm coming back to C++ and am a little confused about class variables that aren't pointers. Given the following code:
#include <iostream>
#include <map>
using namespace std;
class Foo {
public:
Foo() {
bars[0] = new Bar;
bars[0]->id = 5;
}
~Foo() { }
struct Bar {
int id;
};
void set_bars(map<int,Bar*>& b) {
bars = b;
}
void hello() {
cout << bars[0]->id << endl;
}
protected:
map<int,Bar*> bars;
};
int main() {
Foo foo;
foo.hello();
map<int,Foo::Bar*> testbars;
testbars[0] = new Foo::Bar;
testbars[0]->id = 10;
foo.set_bars(testbars);
foo.hello();
return(0);
}
I get the expected output of 5 & 10. However, my lack of understanding about references and pointers and such in C++ make me wonder if this will actually work in the wild, or if once testbars goes out of scope it will barf. Of course, here, testbars will not go out of scope before the program ends, but what if it were created in another class function as a function variable? Anyway, I guess my main question is would it better/safer for me to create the bars class variable as a pointer to the map map?
Anyway, I guess my main question is
would it better/safer for me to create
the bars class variable as a pointer
to the map map?
No. C++ is nothing like Java in this and may other respects. If you find yourself using pointers and allocating new'd objects to them a lot, you are probably doing something wrong. To learn the right way to do things, I suggest getting hold of a copy of Accelerated C++ by Koenig & Moo,
The member variable bars is a separate instance of a "dictionary"-like/associative array class. So when it is assigned to in set_bars, the contents of the parameter b are copied into bars. So there is no need to worry about the relative lifetimes of foo and testbars, as they are independent "value-like" entites.
You have more of a problem with the lifetimes of the Bar objects, which are currently never going to be deleted. If you add code somewhere to delete them, then you will introduce a further problem because you are copying the addresses of Bar objects (rather than the objects themselves), so you have the same object pointed to by two different maps. Once the object is deleted, the other map will continue to refer to it. This is the kind of thing that you should avoid like the plague in C++! Naked pointers to objects allocated with new are a disaster waiting to happen.
References (declared with &) are not different from pointers with regard to object lifetimes. To allow you to refer to the same object from two places, you can use either pointers or references, but this will still leave you with the problem of deallocation.
You can get some way toward solving the deallocation problem by using a class like shared_ptr, which should be included with any up-to-date C++ environment (in std::tr1). But then you may hit problems with cyclical pointer networks (A points to B and B points to A, for example), which will not be automatically cleaned up.
For every new you need a corresponding delete.
If you try and reference the memory after you call delete - where ever that is - then the program will indeed "barf".
If you don't then you will be fine, it's that simple.
You should design your classes so that ownership of memory is explicit, and that you KNOW that for every allocation you are doing an equal deallocation.
Never assume another class/container will delete memory you allocated.
Hope this helps.
In the code below you can pass map of Bars and then will be able to modify Bars outside of the class.
But. But unless you call set_bars again.
It is better when one object is responsible for creation and deletion of Bars. Which is not true in your case.
If you want you can use boost::shared_ptr< Bars > instead of Bars*. That will be more Java like behavior.
class Foo {
public:
Foo() {
bars[0] = new Bar;
bars[0]->id = 5;
}
~Foo() { freeBarsMemory(); }
struct Bar {
int id;
};
typedef std::map<int,Bar*> BarsList;
void set_bars(const BarsList& b) {
freeBarsMemory();
bars = b;
}
void hello() {
std::cout << bars[0]->id << std::endl;
}
protected:
BarsList bars;
void freeBarsMemory()
{
BarsList::const_iterator it = bars.begin();
BarsList::const_iterator end = bars.end();
for (; it != end; ++it)
delete it->second;
bars.clear();
}
};
I'm not new to programming, but after working in Java I'm coming back to C++ and am a little confused about class variables that aren't pointers.
The confusion appears to come from a combination of data that is on the heap and data that is not necessarily on the heap. This is a common cause of confusion.
In the code you posted, bars is not a pointer. Since it's in class scope, it will exist until the object containing it (testbars) is destroyed. In this case testbars was created on the stack so it will be destroyed when it falls out of scope, regardless of how deeply nested that scope is. And when testbars is destroyed, subobjects of testbars (whether they are parent classes or objects contained within the testbars object) will have their destructors run at that exact moment in a well-defined order.
This is an extremely powerful aspect of C++. Imagine a class with a 10-line constructor that opens a network connection, allocates memory on the heap, and writes data to a file. Imagine that the class's destructor undoes all of that (closes the network connection, deallocates the memory on the heap, closes the file, etc.). Now imagine that creating an object of this class fails halfway through the constructor (say, the network connection is down). How can the program know which lines of the destructor will undo the parts of the constructor that succeeded? There is no general way to know this, so the destructor of that object is not run.
Now imagine a class that contains ten objects, and the constructor for each of those objects does one thing that must be rolled back (opens a network connection, allocates memory on the heap, writes data to a file, etc.) and the destructor for each of those objects includes the code necessary to roll back the action (closes the network connection, deallocates objects, closes the file, etc.). If only five objects are successfully created then only those five need to be destroyed, and their destructors will run at that exact moment in time.
If testbars had been created on the heap (via new) then it would only be destroyed when calling delete. In general it's much easier to use objects on the stack unless there is some reason for the object to outlast the scope it was created in.
Which brings me to Foo::bar. Foo::bars is a map that refers to objects on the heap. Well, it refers to pointers that, in this code example, refer to objects allocated on the heap (pointers can also refer to objects allocated on the stack). In the example you posted the objects these pointers refer to are never deleted, and because these objects are on the heap you're getting a (small) memory leak (which the operating system cleans up on program exit). According to the STL, std::maps like Foo::bar do not delete pointers they refer to when they are destroyed. Boost has a few solutions to this problem. In your case it's probably be easiest to simply not allocate these objects on the heap:
#include <iostream>
#include <map>
using std::map;
using std::cout;
class Foo {
public:
Foo() {
// normally you wouldn't use the parenthesis on the next line
// but we're creating an object without a name, so we need them
bars[0] = Bar();
bars[0].id = 5;
}
~Foo() { }
struct Bar {
int id;
};
void set_bars(map<int,Bar>& b) {
bars = b;
}
void hello() {
cout << bars[0].id << endl;
}
protected:
map<int,Bar> bars;
};
int main() {
Foo foo;
foo.hello();
map<int,Foo::Bar> testbars;
// create another nameless object
testbars[0] = Foo::Bar();
testbars[0].id = 10;
foo.set_bars(testbars);
foo.hello();
return 0;
}