-1

Actual Aim: Delete/Destroy the network from the vector and reintroduce it if needed.

So I wrote a small program to try the same.

I am facing problems in deleteing a shared pointer and setting it to nullptr. Directly setting to nullptr will lead to dangling pointer. How can I free that position without causing a memory leak?

#include <iostream>
#include <vector>
#include <memory>
using namespace std;
class ptr{
  public:
  int x;
  ptr(int a):x(a){  }
  ~ptr()
  {
       cout << "destructor\n";
  }
};
int main()
{
    std::vector<shared_ptr<ptr>>v;
    v.push_back(shared_ptr<ptr>(new ptr(100)));
    v.push_back(shared_ptr<ptr>(new ptr(200)));
    v.push_back(shared_ptr<ptr>(new ptr(300)));
    v.push_back(shared_ptr<ptr>(new ptr(400)));
    v.push_back(shared_ptr<ptr>(new ptr(500)));
    auto it = v.begin();
    int i = 0;
    while(i < 5)
    {
        if((*it)->x == 300)
        {
            cout << "300 found \n";
            delete (*it);  // -> Problem is here.
        }
        it++;
        i++;
    }
    return 0;
}
Rasmi Ranjan Nayak
  • 11,510
  • 29
  • 82
  • 122
  • 8
    Never directly call `delete` on a `std::shared_ptr`. The shared pointer object manages deletions. Do `itr->reset();` or `v.erase(it);`, depending on what you want. – Drew Dormann Aug 15 '23 at 17:33
  • @sweenish: I want the vector element to be there and just deallocate the memory – Rasmi Ranjan Nayak Aug 15 '23 at 17:36
  • 3
    The headline question is misleading, then. You don't want to delete a shared_ptr. You want to delete a resource owned by a shared_ptr. – sweenish Aug 15 '23 at 17:38
  • 1
    "Directly setting to nullptr will lead to dangling pointer." unclear what that means. A shared_ptr itself cannot be `nullptr`. It can hold a `nullptr` but most ways to do that do not lead to a dangling pointer – 463035818_is_not_an_ai Aug 15 '23 at 17:41
  • 3
    https://en.cppreference.com/w/cpp/memory/shared_ptr/reset – 463035818_is_not_an_ai Aug 15 '23 at 17:42
  • 1
    `for (auto& p : v) { if (p && p->x == 300) { p.reset(); } }`? – Jarod42 Aug 15 '23 at 17:42
  • There's some weird stuff going on with how you're using smart pointers here. You may find these background questions helpful [What is meant by Resource Acquisition is Initialization (RAII)?](https://stackoverflow.com/q/2321511/11082165) and [What is The Rule of Three?](https://stackoverflow.com/q/4172722/11082165) and [What is a smart pointer and when should I use one?](https://stackoverflow.com/q/106508/11082165) – Brian61354270 Aug 15 '23 at 17:44
  • 3
    _"deallocate the memory"_ - It's a _shared_ pointer. What you can do is to decrease the reference count (with `.reset()`). **If** it reaches zero, **then** the memory will be deallocated. – Ted Lyngmo Aug 15 '23 at 17:46
  • 2
    what is the actual aim? Frankly, using smart pointers to manually manage the memory is somewhat backwards. Just don't call `delete` at all (and `new` should be replaced with `make_shared` too) – 463035818_is_not_an_ai Aug 15 '23 at 17:47
  • Why are you using (smart) pointers at all? It looks like a `std::vector>` would be better. – Ted Lyngmo Aug 15 '23 at 17:55
  • updated the actual aim – Rasmi Ranjan Nayak Aug 15 '23 at 17:55
  • @RasmiRanjanNayak I don't know what _"the network"_ is, but it still looks like `std::vector>` would be better. – Ted Lyngmo Aug 15 '23 at 17:56
  • 1
    Or just std::vector, the vector is more like a temporary view on your data and should not be owning. Then you could have another std::vector that owns the data and you only have to take care that lives long enough. Usually I find shared_ptr's are overused, to not have to think about lifecycle, but it is better to manage lifecycle by design. I usually only need shared_ptr when managing lifetime of objects shared between threads (and ofcourse some other cases where shared ownership really is a thing by design) – Pepijn Kramer Aug 15 '23 at 18:51
  • shared_ptr in the end is a kind of "reference semantics" which is hard to maintain in bigger systems. Watch [cppon22, Value semantics](https://www.youtube.com/watch?v=QthAU-t3PQ4) if you want to know more. – Pepijn Kramer Aug 15 '23 at 18:56
  • @RasmiRanjanNayak: Where's the network? I am really curious how you get a network into a `std::vector`. – Thomas Matthews Aug 15 '23 at 19:39
  • @ThomasMatthews: As I said this is a small piece of code, whcih basically does the same thing I am doing at work. – Rasmi Ranjan Nayak Aug 15 '23 at 19:47
  • The reset definitely did not help me, I fixed my issue in a different way, but anyways I learned something – Rasmi Ranjan Nayak Aug 15 '23 at 19:47

1 Answers1

3

Its a little odd that you are using smart pointers and at the same time want to manually manage the memory.

However, there are several ways to let a smart pointer release the managed object:

  • the most natural: destroy the smart pointer. You could erase it from the vector
  • reset(), effectively the same as...
  • shared_ptr<int>().swap(v[i])
  • ... and more ...

None of that results in a leak or a dangling pointer. You can misuse shared_ptr to create a dangling pointer or to get a memory leak, but you would have to really push hard to do so.


Actual Aim: Delete/Destroy the network from the vector and reintroduce it if needed.

This doesn't sound like smart pointers but rather like std::vector<std::optional<ptr>>. Alternatively consider to use a std::unordered_map<int,ptr> which can model a sparse std::vector where you can erase elements while the others keep their key (=index).

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185