1

When an object has a pointer member, the pointer may point to the part of memory that is not owned by the object. Thus, it may be deallocated without informing the object and cause a dangling pointer (and abundant headaches to debug). For example, let's say I have an object of type ClassHasPointer that has a member variable m_memberPtr of type AnotherClass *.

class ClassHasPointer 
    {
      public:           
             void setMember(AnotherClass* anotherObj) { m_memberPtr = anotherObj; }
             AnotherClass* getMember() { return m_memberPtr; }

      private:
             AnotherClass* m_memberPtr = nullptr;
    }

Now let's say I have an object of AnotherClass called anotherObj that I have defined and used elsewhere in the program. Now, I decide to initialize an object of ClassHasPointer:

ClassHasPointer A;
A.setMember(&anotherObj); // m_memberPtr points to anotherObj

Now, if anotherObj goes out of scope or gets deallocated in any part of the program, m_memberPtr is pointing to junk, thus it's a dangling pointer:

AnotherClass* aBadPtr = A.getMember(); // anotherObj was destroyed, dangling pointer!

We tend to utilize pointers as member variables frequently in classes. I think everytime we do that, it comes with a caveat that the class may not own the data it's pointing to. My questions is how can we ensure we are not accessing the data while it's deallocated without having to unnecessarily copying the data it's pointing to? More importantly, in general, what are the good practices/guidelines/design patterns to avoid this pitfall?

EDIT: I know we can use smart pointers such as std::shared_ptr, but that can be used only if anotherObj was defined on the heap (e.g. AnotherClass* anotherObj = new AnotherClass()). What if that is not the case and I cannot change that? Are there still other ways to get around the dangling pointer problem?

nmnm
  • 47
  • 5
  • 2
    `std::shared_ptr` isn't an option because...? – Zuodian Hu Apr 11 '20 at 22:20
  • 1
    shared_ptr is your friend, will protect you from demons on a dark night – pm100 Apr 11 '20 at 22:45
  • Good point @ZuodianHu. See the EDIT please. – nmnm Apr 11 '20 at 22:49
  • i would create a class that encapsulates a pointer but takes noteof whether or not its on the heap (ie should be released in the upon destruction of the wrapper) – pm100 Apr 11 '20 at 22:51
  • *Are there still other ways to get around the dangling pointer problem?* -- There is no magic -- there is no way `ClassHasPointer` knows whether the address is valid or not. – PaulMcKenzie Apr 11 '20 at 23:01
  • 1
    @nmnm I don't believe there's a general answer to dangling pointers to stack objects, other than nesting your scopes properly (ex. only point to stack objects from objects that will be automatically cleaned up before the pointed-to object; stack objects declared after the pointed-to object, etc.). This is a design issue imo. Sorry. – Zuodian Hu Apr 11 '20 at 23:07
  • 1
    *What if that is not the case and I cannot change that?* -- Well, you're stuck with a design that relies on the client to make sure the pointer has scope longer than `A`. – PaulMcKenzie Apr 11 '20 at 23:15
  • OK. so, I am convinced there is no other way to get around this except for changing the design and/or using smart pointers. Thank you all for your answers! – nmnm Apr 12 '20 at 20:12

1 Answers1

0

If AnotherClass is declared on the stack, you will not be able to avoid a hanging link when exiting scope. And with dynamic allocation, it is better not to use direct memory access, but to use "smart pointers", and using std:: shared_ptr will solve your problem. But if dynamic allocation is not acceptable you can try to avoid pointers and optimize copying using move semantics(What is move semantics?)

loject
  • 46
  • 4