I'm writing a relatively big project in C++ and have a problem with object deletion. The project, to be precise is a roguelike game.
I have a class Npc which is every monster in the game. They are created and stored in a separate class, Storage<Npc>, that is responsible for their management (loading, saving, creation, deletion, etc). Whenever a monster dies, corresponding object npc has to be deleted and destroyed completely. It is not a problem to delete object itself, I just have invoke a method from Storage<NPC>. The problem is that code contains a lot of pointers to this already-dead npc, which are now invalid and trying to use them will cause a lot of issues. For example:
There may be an action he intended to perform before he died.
Tile on which he stood record store a pointer to him.
He may have been involved in some continuous activities, like grappling somebody.
There are a lot of such pointers in the code, so it is nearly impossible to simply track them. What I need is some way to determine that an npc is already dead, and there is no actual object stored on that address, so that parts of code which still have this pointer can adequately react to his death.
I myself have come up with several ideas, but so far none of them seems really good to me:
I could ask Storage<NPC> class if it has an object on such address. The potential problem is that after object deletion, another object may be allocated on the same address, which will cause bugs.
I could notify all locations that could possibly use the invalid pointer. It is a bad idea because number of such locations will increase over time and doing this is a pain.
I could implement some version of smart pointer, but I'm unsure on which one to use.
tl;dr version: I need a solution that will tell me if a pointer points to an object, or it points to a free chunk of memory, or to some other object, allocated after original object deletion.
With the information you provided, what I can suggest is you implement the Observer Pattern.
If there is code that needs to react to the NPC's death, this pattern is the way to go. Code sections having pointer references to your NPC will be notified upon NPC death and null their copy of pointer to NPC and react to the NPC's death however required. The death notification is sent to all observers before the NPC is actually deleted.
With this pattern, you could implement mechanics such as "Hero gains 50 HP for each monster killed", and it's easily scalable.
You can also use Kevin Ballard's suggestion of using shared_ptr if no code needs to actively react to the NPC's death, and just needs to handle the case where the NPC is dead.
How about using weak pointers? If you store the Npc in a std::shared_ptr (C++11, use std::tr1::shared_ptr for C++03), you can then create std::weak_ptrs (C++11 again, use std::tr1::weak_ptr for C++03) that refer to the shared_ptr. When the shared_ptr actually deletes its object, then all the weak_ptrs will be able to figure this out.
Although I have to wonder why you're deleting Npcs that are still being used elsewhere (e.g. that still have actions). If instead of trying to have all these other references discover you've deleted the Npc, you just want the Npc to die once all references disappear, then using a shared_ptr by itself (with no weak_ptr) will work correctly.
One option is to include a reference count in your class. When some other object (a room, for example) is going to hold a pointer to an npc, the room has the responsibility of increasing the npc's reference count. Now, instead of just deleting a dead npc, you flag it as dead (through another new data member if you don't already have the right flag), and only delete if its reference count is zero. The room object also has the responsibility of periodically checking that flag and if it learns the npc is dead, it decrements its reference count (which will cause a post mortem deletion, if the count is now zero).
Related
I have a basic design that consists of three classes : A Data class, A Holder class wich holds and manages multiple Data objects, and a Wrapper returned by the Holder wich contains a reference to a Data object.
The problem is that Wrapper must not outlive Holder, or it will contain a dangling reference, as Holder is responsible for deleting the Data objects. But as Wrapper is intended to have a very short lifetime (get it in a function, make some computation on its data, and let it go out of scope), this should not be a problem, but i'm not sure this is a good design.
Here are some solutions i thought about:
-Rely on the user reading the documentation, technically the same thing happens with STL iterators
-Using shared_ptr to make sure the data lasts long enought, but it feels like overkill
-Make Wrapper verify its Holder still exists each time you use it
-Any idea?
(I hope everyone can understand this, as english is not my native language)
Edit : If you want to have a less theoric approach, this all comes from a little algorithm i'm trying to write to solve Sudokus, the Holder is the grid, the Data is the content of each box (either a result or a temporary supposition), and the Wrapper is a Box class wich contains a reference to the Data, plus additional information like row and column.
I did not originally said it because i want to know what to do in a more general situation.
Only ever returning a Wrapper by value will help ensure the caller doesn't hold onto it beyond the calling scope. In conjunction with a comment or documentation that "Wrappers are only valid for the lifetime of the Holder that created them" should be enough.
Either that or you decide that ownership of a Data is transferred to the Wrapper when the Wrapper is created, and the Data is destroyed along with the Wrapper - but what if you want a to destroy a Wrapper without deleting the Data? You'd need a method to optionally relinquish ownership of the Data back to the Holder.
Whichever you choose, you need to decide what owns (ie: is responsible for the lifetime of) Data and when - once you've done that you can, if you want, use smart pointers to help with that management - but they won't make the design decision for you, and you can't simply say "oh I'll use smart pointers instead of thinking about it".
Remember, if you can't manage heap memory without smart pointers - you've got no business managing heap memory with them either!
To elaborate on what you have already listed as options,
As you suggested, shared_ptr<Data> is a good option. Unless performance is an issue, you should use it.
Never hold a pointer to Data in Wrapper. Store a handle that can be used to get a pointer to the appropriate Data object. Before Data is accessed through Wrapper, get a pointer the Data object. If the pointer is not valid, throw an exception. If the pointer is valid, proceed along the happy path.
I am working on a board based game like checkers. Every tile on the board has certain properties. Before changing the board status, I want to save it's state and use it to undo the last move. As the status changes, all objects are destructed and new ones are created. Is there any way to retain these pointers as well as calling the destructor?
This is a design question more than a pointer/implementation question.
One way to think of undo/redo are two stacks, one for each task
Whenever you make a move, you push the configuration/game state, objects etc.. down the undo stack as one element, when u press undo, u pop an element of that stack, apply it to your game and push this element to the redo stack.
redo stack is cleared when a new move is done
you can't use an object after calling its destructor, pointer or no pointer. you can either copy the object as a whole before pushing it down the stack, or use a pointer to it, whatever suits you
You might be interested in using shared pointers, as they offer you more possibilities
Another approach other than saving the whole game state if you want to effectively use memory, is to just save the changes in the game instead of a snapshot of the whole game, but this usually requires more work, though its the clever approach
You do not want to retain the pointer in this way. If you attempt to access the data through those pointers AFTER they have been deleted, you will get access violations. Once they are deleted the memory they point to should not be accessed through those pointers.
If you take copies of these pointers, they will also have the same address, so accessing that memory through the copies you take will result in the same thing happening. You need to consider a different approach
There are two approaches you can follow to retain game state:
serialize every object that makes up the game state to memory or storage, thus effectively saving the state and being able to come back to it.
retain only the changes from one game state to the other.
I don't think using pointers is central to your design. There's no need to retain the old pointers, and, as far as I can see, there's no need for pointers at all. You either save the old states of the objects themselves, or the series of changes. In this case, I'd go with the latter.
Why don't you use a Link to UNDO list in same tile object ... as a linked list or so, and when user undo the state you manipulate the data in this list and the data in title
I am using boost shared pointers and these pointers are really shared all over the application. There are conditions, where such a shared pointer becomes invalid. For example, a shared pointer to a network resource, that can become invalid because network became unavailable. In such a scenario, where the shared pointer becomes invalid, i would like all objects to stop using it. How can i send a message to all objects that the pointer is invalid. If it was a normal pointer, i could set it to null and all client code should be checking for null pointer before using it. But, in case of a shared pointer, which keeps reference count, how can i achieve similar functionality ?
You can use weak pointers. That is, the code that handles the network events has the shared_ptr<Res> while everybody else has a weak_ptr<Res>. Now,
when the resource becomes unavailable, just reset the shared_ptr to NULL;
when a client wants to use the resource, call lock() into the weak_ptr and test whether the returned shared_ptr is valid before using.
If it was a normal pointer, i could set it to null and all client code should be checking for null pointer before using it.
I doubt that. You'd then have copies of that raw pointer that point to invalid objects. You'd think that would solve the problem, but it doesn't. It amplifies it.
The fact is that the shared pointer itself doesn't become invalid, the object it contains does. So, logically, whether it's still safe to use it should be contained in the object, not the shared pointer.
a shared pointer to a network resource, that can become invalid because network became unavailable.
Just throw an exception when you attempt to call a method that attempts to use the network...
I would be inclined to follow the pattern used by standard streams: have an object that represents the resource, which can enter an error state and/or throw an exception when it detects (or is informed) that the network is no longer available. If you can't change the existing resource class, then this new object can hold the existing resource object (that currently all your users have shared pointers to), and the users can share the new object.
Unless you need all the users of this resource to respond promptly when it becomes unavailable, there doesn't seem any point trying to propagate a message to them all. If you just want them to stop using it, they can do that the next time they try to use it, and discover that it doesn't work any more. If they do really need a message, then write something to keep a list of them all, and call some function on them when the event that they're interested in occurs. This is called the Observer pattern or "listeners", and armed with those search terms you can find implementations and alternatives.
Ideally, users should be able to check for the error state either as part of using the resource, or immediately afterwards. Testing before use is usually error-prone, since it creates a window in which the network perhaps could become unavailable after the test but before it's used. Once your code has to handle that case correctly you might as well make it the only case, by not bothering to check in advance.
You need to store more information. You could put the resource together with a bool in a tuple, or you could use boost::optional, and set it to none when you want to invalidate it.
You almost certainly shouldn't be using shared pointer for this, since
its semantics don't correspond to what you need. Shared pointer
implements a sort of poor man's garbage collection, where the object
ceases to exist when there are no more pointers to it; you need the
opposite, that the pointers to the object cease to exist when there is
no more object. (A reverse garbage collection, so to speak.)
I've used a ManagedPtr in the past; the pointer registers itself with
the object, which must derive from a ManagingObj class which sets the
pointers to null in its destructor. This works sometimes, but it still
doesn't remove entries from lists, etc. where the other objects may be
keeping it. And in practice, other objects which know about your
network resource object may want to take specific actions when it
disappears. In the end, you almost always need to use the observer
pattern: any object which acquires a pointer to your object registers
with it to be notified in case of its demise.
Generally I follow the Google style guide, which I feel aligns nicely with the way I see things. I also, almost exclusively, use boost::scoped_ptr so that only a single manager has ownership of a particular object. I then pass around naked pointers, the idea being that my projects are structured such that the managers of said objects are always destroyed after the objects that use them are destroyed.
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Smart_Pointers
This is all great, however I was just bitten by a nasty little memory stomp bug where the owner just so happened to be deleted before objects that were using it were deleted.
Now, before everyone jumps up and down that I'm a fool for this pattern, why don't I just use shared_ptr ? etc., consider the point that I don't want to have undefined owner semantics. Although shared_ptr would have caught this particular case, it sends the wrong message to users of the system. It says, "I don't know who owns this, it could be you!"
What would have helped me would have been a weak pointer to a scoped pointer. In effect, a scoped pointer that has a list of weak references, that are nulled out when the scoped pointer destructs. This would allow single ownership semantics, but give the using objects a chance to catch the issue I ran into.
So at the expense of an extra 'weak_refs' pointer for the scoped_ptr and an extra pointer for the 'next_weak_ptr' in the weak_ptr, it would make a neat little single owner, multiple user structure.
It could maybe even just be a debug feature, so in 'release' the whole system just turns back into a normally sized scoped_ptr and a standard single pointer for the weak reference.
So..... my QUESTIONS after all of this are:
Is there such a pointer/patten already in stl/boost that I'm
missing, or should I just roll my own?
Is there a better way, that
still meets my single ownership goal?
Cheers,
Shane
2. Is there a better way, that still meets my single ownership goal?
Do use a shared_ptr, but as a class member so that it's part of the invariant of that class and the public interface only exposes a way to obtain a weak_ptr.
Of course, pathological code can then retain their own shared_ptr from that weak_ptr for as long as they want. I don't recommend trying to protect against Machiavelli here, only against Murphy (using Sutter's words). On the other hand, if your use case is asynchronous, then the fact that locking a weak_ptr returns a shared_ptr may be a feature!
Although shared_ptr would have caught this particular case, it sends the wrong message to users of the system. It says, "I don't know who owns this, it could be you!"
A shared_ptr doesn't mean "I don't know who owns this". It means "We own this." Just because one entity does not have exclusive ownership does not mean that anyone can own it.
The purpose of a shared_ptr is to ensure that the pointer cannot be destroyed until everyone who shares it is in agreement that it ought to be destroyed.
Is there such a pointer/patten already in stl/boost that I'm missing, or should I just roll my own?
You could use a shared_ptr exactly the same way you use a scoped_ptr. Just because it can be shared doesn't mean you have to share it. That would be the easiest way to work; just make single-ownership a convention rather than an API-established rule.
However, if you need a pointer that is single-owner and yet has weak pointers, there isn't one in Boost.
I'm not sure that weak pointers would help that much. Typically, if a
component X uses another component Y, X must be informed of Y's demise,
not just to nullify the pointer, but perhaps to remove it from a list,
or to change its mode of operation so that it no longer needs the
object. Many years ago, when I first started C++, there was a flurry of
activity trying to find a good generic solution. (The problem was
called relationship management back then.) As far as I know, no good
generic solution was every found; at least, every project I've worked on
has used a hand built solution based on the Observer pattern.
I did have a ManagedPtr on my site, when it was still up, which behaved
about like what you describe. In practice, except for the particular
case which led to it, I never found a real use for it, because
notification was always needed. It's not hard to implement, however;
the managed object derives from a ManagedObject class, and gets all of
the pointers (ManagedPtr, and not raw pointers) it hands out from it.
The pointer itself is registered with the ManagedObject class, and the
destructor of the ManagedObject class visits them all, and "disconnects"
them by setting the actual pointer to null. And of course, ManagedPtr
has an isValid function so that the client code can test before
dereferencing. This works well (regardless of how the object is
managed—most of my entity objects "own" themselves, and do a
delete this is response to some specific input), except that you tend
to leak invalid ManagedPtr (e.g. whenever the client keeps the pointer
in a container of some sort, because it may have more than one), and
clients still aren't notified if they need to take some action when your
object dies.
If you happen to be using QT, QPointer is basically a weak pointer to a QObject. It connects itself to the "I just got destroyed" event in the pointed-to value, and invalidates itself automatically as needed. That's a seriously hefty library to pull in for what amounts to bug tracking, though, if you aren't already jumping through QT's hoops.
This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
Should objects delete themselves in C++?
In my application, I'm creating many objects that "own themselves" - in the sense that after they are created and told to "go," only the object itself can determine when it should be deleted.
For example, if I was writing a game, I might have multiple Enemy objects. Only the Enemy object knows when it should die.
As a result, I end up using delete this inside some of the member functions inside the Enemy object. Is this bad form? Is this something I should avoid, and if so, what is the correct way to handle this type of situation?
The thing to be careful of is that if too many member functions have self-deletion as a side effect, it's easy to accidentally use a reference to the object after it's deleted.
One approach to avoid this is to defer the deletion - that is, put the object on a list, and from your game's main loop, delete everything on that list at the start/end of a tick.
Depends on the memory management strategy. There are cases that it really makes sense and it's the correct thing. For instance, in a reference counting system like COM, the object would do a delete this when the refcount gets down to zero.
For example, if I was writing a game, I might have multiple Enemy
objects. Only the Enemy object knows
when it should die.
The enemy object may know when it enters a "dead" state, yes. But that is not necessarily the same as "the object should be deleted".
Think of all the other objects that may have a reference to it? They may at any time attempt to call a function on the Enemy object (say, TakeDamage()), and if the object has been deleted without informing them, you'll probably have a crash. How do they know that the Enemy they're shooting at is dead?
So the Enemy object knows when it is dead, but not when it should be deleted. It does not own itself.
Who does own it then?
The game world may be a good bet. When the enemy dies, it sends a message to the game world saying that it is dead, and the game world could then be responsible for making sure no one holds a pointer to it, and finally, when it is safe to do so, deleting the object.
It seems odd to me, i myself would prefer someone or something getting rid of them. The fear of someone referencing the object is just terrifying to me. It also seems very possible for a "child" method to unknowningly destroy the object. When you return to a higher level method: you're operating on a non-existant object.
It sounds like you're inventing referencing counting, perhaps explicitely use the reference count pattern.
Or have the objects add themselves to a "to be destroyed" list - and you have yourself a garbage collection system.
As long as the Enemies manage all the references to them (eg. list of units, list of units in groups etc.) it's OK (and used quite often).
But if you want to be on the safer side, the Enemies should register themselves for some destruction routine run at some "safe spot" in the program execution (for an example, see QObject::deleteLater() in Qt.
You could use shared_ptrs to objects to have them automatically clean up when no references to them are available anymore.
Or call the destructor on the class.
To be honest you should try to stick away from that. Otherwise you might delete something that is used by something else and finish off by having a really odd result and probably some memory leak with it.
I think that the object should delete its resources in the destructor. Your class should use another class to know when the enemies are dead.
The referring object(s) should do the deletion, and they should do so by asking the object if the conditions for deletion are met. One of the conditions (besides being eliminated from use in the game) are how many other objects still refer to the object. This is something that can be tracked with static reference counting. Generally, if you write it carefully, you might be able to build it in such a way that enemies are only tracked in one place in your game loop. That place will check collisions and other conditions, and when it's ready to delete the object it will not have to ask if deletion is okay because it knows it's the only client, and can safely dereference what it allocated.
Abstractly, I don't think you want an object deleting itself.
What you want to do is create a control structure that retrieves a SIGNAL or message from the object that it's time to "die", in this case, and the control structure will "delete" or take the particular necessary action on the object.
This way, you leave the control of the object existing or not on the control structure, and when everything has a centralized control unit, you prevent potential calls to deleted objects.
Also, remmeber to differentiate between a soldier "dying" as you say, and an object being actually "deleted" from memory. The dying portion, the object itself can accomplish by setting a flag, such as "dead = true." But the deletion of the object from memory should be accomplished by the control structure I'm referring to.