0

After executing lines 40 and 41 below, the debugger is telling me that the weak reference count for the std::shared_ptr's a and b is 2.

enter image description here

The ctor for Value is not storing any strong or weak references to these objects:

struct Value : public std::enable_shared_from_this<Value> {
    double data;
    double grad;
    std::function<void()> _backward;
    std::vector<std::shared_ptr<Value>> _prev;
    std::string _op;
    Value(double data,
          const std::vector<std::shared_ptr<Value>>& _children = {},
          std::string _op = "")
        : data{data}, grad{0}, _backward{[]{}}, _prev{_children}, _op{_op} {}
    ...
};

I expect there to be only single strong references to these objects (we can see the expected strong reference counts of 1 in the shared_ptr control block). In fact there are no explicit std::weak_ptr's being use anywhere in this code base? Is the debugger itself storing weak reference's to these objects (i.e., a Heisenbug issue)?

Line 42, which has yet to be executed, invokes an overloaded + operation, but I don't see how this would affect the current (or future for that matter) weak reference counts:

std::shared_ptr<Value> operator+(const std::shared_ptr<Value>& A,
                                 const std::shared_ptr<Value>& B) {
   ...
}
curiousguy
  • 8,038
  • 2
  • 40
  • 58
wcochran
  • 10,089
  • 6
  • 61
  • 69
  • 6
    `std::enable_shared_from_this` typically contains a `std::weak_ptr`. – Drew Dormann Apr 18 '23 at 14:58
  • 1
    1 is probably from the object itself as the control block of the pointer and the pointed to object share the same single allocation. The other is probably a member of `enable_shared_from_this` – NathanOliver Apr 18 '23 at 15:01
  • @DrewDormann I was suspecting this ... why would the count be 2 then? – wcochran Apr 18 '23 at 15:02
  • @NathanOliver if the control block is considered a weak reference then the weak reference count would always be at least 1 (?) – wcochran Apr 18 '23 at 15:05
  • 1
    @wcochran That has been my experience whenever using `make_shared`. – NathanOliver Apr 18 '23 at 15:08
  • 2
    Offtopic `operator+` for smart pointers is strange and I would discourage from defining it for any pointed type. – Marek R Apr 18 '23 at 15:15
  • I have confirmed that the weak reference count is only 1 under g++/Linux whereas its 2 under macOS/Xcode -- so 1 is from the `std::enable_shared_from_this` and the other from the debugger (Heisenbug). – wcochran Apr 18 '23 at 15:23
  • @MarekR I am creating a computation graph and each node may have multiple references so shared_ptr's seemed the way to go. – wcochran Apr 18 '23 at 15:26
  • thats ok, but usually you overload operators for the objects not for their pointers. The latter is confusing – 463035818_is_not_an_ai Apr 18 '23 at 15:44
  • @MarekR operator overloading is just syntactic sugar -- I could have just defined a function `create_addition_node(...)` but overloading `+` makes graph creation code easy to read. – wcochran Apr 18 '23 at 15:50
  • You are free to come up with any implementation of the pair (shared|weak)_ptr with a zero weak count value, and a triplet *_ptr+enable_shared_from_this without the value being 2, please provide any suggestions to do that. The implementers go the easy way and like virtual functions being done via vptr and vtable in each and every case because that's the only cheap and simple and sane approach, what you see is the easy and sane default impl. – curiousguy Apr 24 '23 at 05:02

0 Answers0