0

This is more a disussion than a question, but still.. A few days ago I found myself having a big problem in my program. I'll try and be brief with the situation I encountered. My plan was to have a callback function being executed every time a certain key, let's say space, was RELEASED. It had a few parameters, however the most important one was a pointer to some object, in that case it was an entity object for my game. That entity was stored in a vector as an unique_ptr, hence the memory was cleared up for me when I deleted that space in the vector.

Good enough, right? Well, the problem was that if that certain entity was deleted from memory, and right in the next tick of the program I released the space key, that callback function was executed with a pointer to that deleted entity. Silly as I was, I thought that pointer was going to magically turn itself to nullptr, hence not continuing the flow of the callback, "I did check if the pointer was null in the beginning of the function, and return if it was indeed null."

As you can imagine, the pointer was not null even after that entity was deleted. It pointed to some garbage azz trash memory that no one cared about. Eventually, I came across weak_ptr, changed the unique_ptr to a shared_ptr in the vector, and passed the entity as a weak_ptr instead of raw pointer to my callback. Finally, I checked if the weak_ptr was nullptr with the "lock()" function, which worked pretty neat for me. If the memory was deleted, that lock() would return null, and if not, it would return a shared_ptr inside my function.

You see, the reason I didn't want to use shared instead of unique was that I didn't want any class to "own" my entity. I wanted my entity to be destroyed as soon as either the vector goes out of scope or it's cleared. Nevertheless, that single ownership can be achieved with shared_ptr IF we pass pointers as a weak_ptr, so no other class will "own" my entity. In conclusion, std::weak_ptr is acually a good solution.

Now my question - is there a solution for dangling pointers other the weak_ptr? (Yes, I had set that unique_ptr to nullptr right before deleting the vector. But it did not change anything. The dangling pointer still pointed to some garbage memory.)

  • 1
    "You see, the reason I didn't want to use shared instead of unique was that I didn't want any class to "own" my entity. " thats the exact inverse use case, use `unique_ptr` if you want it owned, use `shared_ptr` if you want non owned. – pm100 Apr 12 '22 at 23:53
  • Hear me out. If my vector has a shared pointer to an object, and then I have a reference to that object in another class as another shared pointer, when I delete my vector, which by the way was supposed to be the only one with ownership, the object will not be deleted from memory, because a shared pointer to that object is still alive in another class. That doesn't happen with unique pointers, as I was passing raw pointers to that unique pointer around. The ownership was exclusive to that vector. – Pedro Sarmento Apr 12 '22 at 23:59
  • I should've clarified that the only class that I wanted to own my object was the class that was holding the vector. – Pedro Sarmento Apr 13 '22 at 00:03
  • 1
    "That entity was stored in a vector as an unique_ptr, hence the memory was cleared up for me when I deleted that space in the vector." Presumably there is _something_ creating and destroying the entity - so you're generating a `unique_ptr` from that raw pointer, but not using the `unique_ptr` to manage its lifetime? That's just not going to work. You'd be better off specifying the "custom deleter" parameter of the `unique_ptr` to invoke whatever you're using to "externally" delete the entity. – Den-Jason Apr 13 '22 at 00:07
  • e.g. https://stackoverflow.com/questions/19053351/how-do-i-use-a-custom-deleter-with-a-stdunique-ptr-member – Den-Jason Apr 13 '22 at 00:08
  • @Den-Jason I created the entity as an unique_ptr and used the std:move() into that vector. So the lifetime was bound to that place in the container. I was just passing around raw pointers to that entity, which caused the dangling pointer after that entity was released from memory. – Pedro Sarmento Apr 13 '22 at 00:12
  • @PedroSarmento Why not provide some code snippets to clarify your points? – Den-Jason Apr 13 '22 at 00:14
  • Also, if you're passing the raw pointer of a `unique_ptr` to share it, that's not going to work. In that case, use `shared_ptr`, or `weak_ptr` if you want it to behave like a "cache" of some sort. – Den-Jason Apr 13 '22 at 00:17
  • "...if you're passing the raw pointer of a unique_ptr to share it, that's not going to work..." @Den-Jason yes that was what I kinda found out. I just wanted to pass references of that entity around my program but keeping the vector as the only owner of that entity. Eventually I found out about weak pointers, which saved me. I was just curious if there were other solutions for dangling pointers instead of just weak pointer. – Pedro Sarmento Apr 13 '22 at 00:22
  • I think it's simply a case of "use shared_ptr if you want to make damn sure the entity remains in memory until all of its uses are complete", or use "weak_ptr if you want to share an entity but might choose to delete it at some point" (as you would in a cache). You create a dangling pointer problem when you use raw/naked pointers (because they are untracked). It sounds to me that you've "happened upon" one use case for weak pointers ;) – Den-Jason Apr 13 '22 at 00:24
  • See https://stackoverflow.com/questions/12030650/when-is-stdweak-ptr-useful – Den-Jason Apr 13 '22 at 00:29
  • and this talk from Herb Sutter - `CppCon 2016: Herb Sutter “Leak-Freedom in C++... By Default.”` - https://www.youtube.com/watch?v=JfmTagWcqoE – Den-Jason Apr 13 '22 at 00:33
  • 1
    @Den-Jason Well, then there's no other solution for dangling pointers other than weak pointers, I guess. It's very useful, don't get me wrong. But I thought there were other ways that didn't require the use of weak pointers to check if a pointer has been dangled. Cheers – Pedro Sarmento Apr 13 '22 at 00:33
  • @PedroSarmento I would re-phrase that as, "the solution for dangling pointers is to use smart pointers. They come in different flavours and you use the one that's best suited to your specific use-case" – Den-Jason Apr 13 '22 at 00:35

0 Answers0