Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I might have some aspects of this wrong, this is really the first time I have dealt much with shared pointers in particular.
I am working on traversing a tree. My tree consists of a linked list, with a vector of shared pointers representing all children for each node. To traverse, I am (to begin with) trying to do this:
//--------------------------------------------------------------
void setupMesh(){
Mesh mesh;
shared_ptr<Mesh> shared_mesh(&mesh);
meshes.push_back(shared_mesh);
checkChildren(root, &temp_mesh);
}
//--------------------------------------------------------------
void checkChildren(Node * temp_node, Mesh * temp_mesh){
if(!temp_node->children.empty()){
for(int i = 0; i < temp_node->children.size(); i++){
if(i > 0){
shared_ptr<Mesh> new_mesh(new Mesh);
meshes.push_back(new_mesh);
}
temp_node = temp_node->children[0].get();
checkChildren(temp_child, temp_mesh);
}
}
}
My tree structure itself seems fine, but it's more an issue with how I'm traversing it, and how I'm keeping track of pointers. It is currently returning bad access errors. From what I can tell, it looks like I am inserting a pointer to a temporary object, temp_node, and temp_mesh.
To simplify the process I had in mind:
Loop through all children that belong to node[0] (root).
For each of the children, perform this same loop on them. If the child is child[0], continue adding it's coordinates to the same temp_mesh object, but if it is another child, create a new mesh to store it, and all first children of it.
Any new meshes should have a pointer pushed back into the meshes vector (vector>).
Does anyone have advice on how I could do this more efficiently, or where I'm going wrong with handling these pointers in memory.
It is currently returning bad access errors.
Then that's what you should worry about as your first priority. That's a serious bug.
From what I can tell, it looks like I am inserting a pointer to a temporary object, temp_node, and temp_mesh.
This aren't "temporary" objects, that means something different (why do you keep using "temp" in your variable names?), but you're right about the problem:
shared_ptr<ofMesh> shared_mesh(&temp_mesh);
This creates a shared_ptr which owns the pointer &temp_mesh and so will delete it when there are no more shared_ptr objects that share ownership of that pointer.
But that pointer is the address of an automatic variable (aka stack variable) which goes out of scope at the end of the block. You don't "own" that object, the block scope of that function manages it automatically. If you don't own it then you can't give ownership of it to the shared_ptr, because it's not yours to give away.
When the scope ends the automatic variable temp_mesh will be destroyed automatically, but there are still shared_ptr objects that hold that pointer, thinking they own it. When you try to access the object through those shared_ptr objects you access a destroyed object, after its lifetime has ended. Then when there are no more shared_ptr objects that own the pointer it will be deleted, but it wasn't created with new so that's a serious bug. (You get this right in the other function, so I'm not sure why you've done it wrong in setupMesh).
If you want a shared_ptr to own an object you need to create it with new, or preferably create it with std::make_shared: *
shared_ptr<ofMesh> mesh = std::make_shared<ofMesh>();
mesh0->setMode(OF_PRIMITIVE_LINE_STRIP);
mesh->setupIndicesAuto();
mesh->addVertex(root->location);
mesh->addColor(ofColor(0));
meshes.push_back(shared_mesh);
checkChildren(root, mesh.get());
This creates an object that is owned by a shared_ptr right away, so there's no problem of transferring ownership of something that can't be owned by a shared_ptr.
* Or you can use a "null deleter" but that's way too advanced for this answer, and won't make it OK to use automatic variables like this.
Related
Please forgive this question because it is likely along the lines of being elementary. Also, I have extensively googled this, but all I found were examples using implementations that quite obviously result in a memory leak.
Take note of the following pseudo code:
void myArbitraryFunc(){
...
// Create Pointer to parent class
MyParentClass* parent = (MyParentClass*)this.getParent();
parent->doSomething(someData);
...
}// Is parent destroyed here?
By destroyed I don't meam the parent class, I mean the pointer "parent", which I declared in the function body. It is destroyed when it falls out of scope, correct? If yes, why? And how would I create a duplicate of the class pointer without it being tied to the original parent?
The pointer parent is destroyed. What it points to, however, is not destroyed.
The pointer itself is just a variable on the stack, and goes away when the stack unwinds, when the current scope ends. It is conceptually no different from this code:
void myArbitraryFunc() {
...
int parent = 42;
....
} // parent goes away
The way to think about it is that a pointer is just a number, that number being the memory address of the object pointed to.
Now in your example, we presume that the MyParentClass object itself was created by something else, and is owned by something else, so myArbitraryFunc is not responsible for deleting it.
A pointer is really just a number, and "address" of the object. Imagine memory as a giant set of boxes, with a number. You ask the system to create an object, and it does so, and tells you that the object is in box 42. Obviously writing copies of '42' isn't doing anything to the object itself. It's just making lots of copies of the address.
Edit
I suppose the code below would assume I have an overloaded version of addChild() that accepts a Sprite already wrapped in a unique_ptr, where taking ownership would be fine. Just thought I'd mention that before someone else did. :) . I made up all the code here after a very long day, so please take it as pseudo code quality meant only to demonstrate the issue at hand.
Original Question
I'm writing a framework where there is a display list, parents/children etc. I'm thinking that using unique_ptr<Sprite> for example is the way to go here, since when you add a child to a parent display object, it's only logical that the parent now becomes the sole owner of that child.
However, there will be methods available such as getChildAt(index) and getChildByName, etc, which I believe should return a reference or pointer value, since these methods are simply meant to expose a child to operations, not transfer ownership.
Finally, the issue and the reason for this question, is in the following situation. Lets assume we have two Sprite objects which are children of the root of display list, Stage. Let's say we have a third child Sprite.
Stage newStage;
std::unique_ptr<Sprite> parentOne(new Sprite);
std::unique_ptr<Sprite> parentTwo(new Sprite);
newStage.addChild(parentOne); //Stage takes ownership of parentOne
newStage.addChild(parentTwo); //Stage takes ownership of parentTwo
std::unique_ptr<Sprite> someChild(new Sprite);
parentOne->addChild(someChild) //parentOne takes ownership of someChild.
Now, somewhere else lets say in the code base of the game or whatever using this framework, someChild is accessed via getChildAt(int index);.
Sprite& child = parentOne->getChildAt(0);
It would be perfectly legal for the following to then happen.
parentTwo->addChild(child);
The addChild method handles removing the child from it's previous parent, if a parent exists, so that the new parent can now make this child part of its section of the display list.
I'm returning the child(ren) from each sprite as a reference or pointer, because we don't want to hand off ownership (in methods such as getChildAt()), just provide access to the child. We don't want to hand it off as a unique_ptr and have it fall out of scope and die.
However, as I say, it would be perfectly legal and normal for this child (now accessed by a reference or pointer) to be passed off to another container (lets say in a drag and drop operation, dragging an item from one list to another). The problem we have now is that the unique ownership needs to be transferred from one parent to another, but we only have a reference or raw pointer.
I'm wondering what a sane solution to this problem would be. If I return a pointer, is it possible to transfer the ownership correctly at this stage?
void Sprite::addChild(Sprite* newChildToOwn)
{
/* by checking newChildToOwn->parent we can see that the child is already owned
by someone else. We need to not only remove the child from that parents' part of the
display list and add it here, but transfer exclusive object ownership of newChildToOwn
to this->.
*/
}
The release method gets you the pointer to the object and releases it from the unique_ptr
http://en.cppreference.com/w/cpp/memory/unique_ptr/release
For your structure, you should probably have method called releaseChild(index) that handles you the ownership by returning pointer.
To transfer ownership you need to have access to the unique_ptr as the raw pointer knows nothing of how it is being used.
Would it work to have the remove child method return the unique_ptr so that the object is kept alive during the transfer and the Sprite will be able to take the ownership? This will allow references to be used in other places as you have already.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
In some code I have been working on, I am passing pointers into classes that aren't necessarily managed specifically by the class to which they are passed. If the class is destroyed then I check to see if the pointer's memory has or has not already been deallocated. The problem I have is that, if a pointer is deallocated and set to NULL before the class's destructor is called then I end up with a dangling pointer. The class ends up seeing the pointer is still non-NULL and tries to delete it which causes a segmentation fault. The best solution I could think of for this is to store the pointer by reference as shown below:
class PtrReferenceClass {
public:
PtrReferenceClass(int*& i_) : i(i_) {}
void run() {
if(i == NULL)
cout << "pointer is null\n";
else
cout << "pointer isn't null\n";
}
int*& i;
};
int main() {
int* i = new int(5);
PtrReferenceClass test(i);
test.run();
delete i;
i = NULL;
test.run();
return 0;
}
As expected, the output is:
pointer isn't null
pointer is null
Ofcourse when the pointer isn't store by reference I end up with a dangling pointer.
My question is as to whether or not this is generally considered to be a good programming practice. Are there any drawbacks to this solution or is there a better convention?
It depends upon what you are trying to accomplish.
If you want the memory around for your class use C++11's std::shared_ptr everywhere instead of an int*.
If you don't need the memory around for your class use C++11's std::weak_ptr.
As far as holding onto pointers in a class, that's not bad if they're wrapped in one of C++'s pointer wrappers. You can just hang onto raw pointers, but in general you should only do that if speed is an extreme concern.
You could check for NULLness in the destructor of PtrReferenceClass. A much better alternative whould be to use a shared_ptr or really clarify ownership of i.
Agree with #Paranaix in main thread comment, as well as #ToniBig, I can't really think of a situation where you would need this. Such a thing is probably to protect against horrible programmer error. You should also keep in mind that you are storing a reference to the pointer i, and that reference will be left dangling when the pointer i goes out of scope, regardless of whether the memory i refers to has been deallocated or not. SO in conclusion, please don't do this.
All you've done is trade one lifetime problem for another. The new problem may be easier to solve... or it may not.
Now you can detect that the object is gone... as long as something has kept the pointer variable alive.
Think carefully about your variable lifetimes, and whether a reference-to-pointer (or equivalently, pointer to pointer) makes sense should become clear.
There certainly are cases where double indirection is valuable. I will leave you with a quote: "Any problem in computer science can be solved by adding another layer of indirection"
These are options :
give ownership to class and manage lifecycle inside it.plus with safe
setter method for changing it when you want. Again do it if you have to create or obtain that pointer outside,otherwise just do all inside.
only pass that pointer to methods that will use it and when
needed.void run(int* i).
I'm not new to C++ but I do mostly work in C# and other managed languages usually so I'm not that well versed in shared pointers etc.
I basically have a 3-dimensional map of shared_ptrs to objects of a custom class (for 3d purposes).
These shared_ptrs live inside the map and are referenced all over the project, so far so good. For a specific piece of functionality I store some of these shared_ptrs in a vector to be iterated over later in the code but this is where things seem to break down.
Say I have 100 of these objects with their pointers stored in the 3d map and 3 of them are added to the vector because they have special properties for functionality. When I'm traversing the vector I call functions on these 3 objects. This all works fine until the for loop (for the iteration) hits it's second run on element [1] of the vector, at this point element [0] is full of corrupted data (but element[1] needs to access element[0] to perform one of the functions) and this is where I get an error.
As I said, I'm not that well versed in shared_ptrs but I thought that the data wouldn't be corrupted because the actual object is created in the creation of the 3-dimensional map - also, the vector hasn't gone out of scope yet because I am only in the 2nd run through the for loop (with 3 objects and so 3 iterations).
I know I must be doing something wrong but I have no idea how to debug this further - basically when I step through the code and it comes to the 2nd run of the for loop, if I look at element [0]'s shared_ptr in the vector (using VS) it is all corrupted.
Here is the loop of the code so you can see. The vector is created in the constructor of the class this code is in and the map (where the shared_ptrs and objects are created) is in the main class of the application. Also, getAdjacent takes objA and objB as pointers and so "fills" objB with the data of the adjacent object to objA:
for(vector<shared_ptr<ObjectClass>>::iterator iterator = objects.begin(); iterator != objects.end(); iterator++)
{
shared_ptr<ObjectClass> objA = (shared_ptr<ObjectClass>) iterator->get();
shared_ptr<ObjectClass> objB;
m_3DMap->getAdjacent(objA, objB);
objA->move(objB);
}
Could it be something to do with the cast I perform on iterator->get()? I couldn't see any other way to do it because if I don't have that cast there VS says that it can't convert from ObjectClass* to shared_ptr which is confusiong to me too because I thought I have a vector of shared_ptrs?..
Thanks for your time and it would be great if anyone could help.
For starters, you should call get() on a shared_ptr very rarely. And using that pointer to init another shared_ptr you MUST NOT do, ever.
The raw pointer you construct the smart pointer from is passed for ownership. And ownership must be exclusive. The way you use it two shared_ptrs will own the same object resulting a premature, and later a double delete at some point, both putting you to UB land.
This is somewhat better than your original, but without seeing code chances are good that getAdjacent is also broken in some way.
for(auto i = objects.begin(); i != objects.end(); ++i)
{
const auto& objA = *i;
shared_ptr<ObjectClass> objB;
m_3DMap->getAdjacent(objA, objB);
objA->move(objB);
}
signature of getAdjacent should be something like
void getAdjacent(shared_ptr<ObjectClass> const& objA, shared_ptr<ObjectClass>& objB);
to have fighting chance.
Okay I found the problem I had.
It was in part to do with what Balog Pal said about putting the shared_ptrs in a vector even though they live in a map so I changed this so that the vector held pointers to the shared_ptrs. Although this may still be bad practice, it got around the issue - especially as the vector was local and lost scope after the function exited.
The original vector approach was implemented as I was getting a dereference on my map iterator somewhere in the function and so I decide to leave all map manipulation outside the iterating (hence storing the 'special' objects in the vector to be iterated over later).
I have now changed the implementation to get rid of this inefficiency as my manipulation functions now return a new map iterator and thus negating the problem.
It would have been nice if the error message was somewhat more helpful that it was because it took me some time to realize the iterator became invalidated because I had an insert() buried in one of the functions that was called on the 'special' objects.
Although this answer doesn't really answer the exact question I asked, it answers the problem as a whole and why I designed the function in the way I did in the question.
Thanks for the help Balog and itwasntpete for the answers and comments.
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).