【问题标题】:How to avoid pointing to deallocated memory (dangling pointers) in classes with pointer members如何避免在具有指针成员的类中指向已释放的内存(悬空指针)
【发布时间】:2020-07-24 15:03:31
【问题描述】:

当一个对象有一个指针成员时,指针可能指向不属于该对象的那部分内存。因此,它可能会在不通知对象的情况下被释放并导致指针悬空(以及大量的调试问题)。例如,假设我有一个 ClassHasPointer 类型的对象,它有一个 AnotherClass * 类型的成员变量 m_memberPtr

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

      private:
             AnotherClass* m_memberPtr = nullptr;
    }

现在假设我有一个名为 anotherObjAnotherClass 对象,我已经在程序的其他地方定义并使用了它。现在,我决定初始化一个ClassHasPointer的对象:

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

现在,如果 anotherObj 超出范围或在程序的任何部分被释放,则 m_memberPtr 指向垃圾,因此它是一个悬空指针:

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

我们倾向于在类中经常使用指针作为成员变量。我认为每次我们这样做时,都会附带一个警告,即该类可能不拥有它所指向的数据。我的问题是,我们如何确保在数据被释放时不访问数据,而不必不必要地复制它指向的数据?更重要的是,一般而言,避免这种陷阱的良好做法/指南/设计模式是什么?

编辑:我知道我们可以使用智能指针,例如std::shared_ptr,但只有在堆上定义了另一个Obj 时才能使用(例如AnotherClass* anotherObj = new AnotherClass())。如果不是这种情况,我无法改变怎么办?还有其他方法可以解决悬空指针问题吗?

【问题讨论】:

  • std::shared_ptr 不是一个选项,因为...?
  • shared_ptr 是你的朋友,会在漆黑的夜晚保护你免受恶魔的伤害
  • 好点@ZuodianHu。请参阅编辑。
  • @nmnm 我不相信悬空指向堆栈对象的指针有一个通用的答案,除了正确嵌套你的范围(例如,只指向堆栈对象之前将自动清理的对象)指向对象;在指向对象之后声明的堆栈对象等)。这是一个设计问题。对不起。
  • 如果不是这种情况,我无法改变它怎么办? -- 好吧,你的设计依赖于客户端来确保指针具有范围大于A

标签: c++ class pointers design-patterns dangling-pointer


【解决方案1】:

如果在堆栈上声明了 AnotherClass,则在退出作用域时将无法避免挂起的链接。并且对于动态分配,最好不要使用直接内存访问,而是使用“智能指针”,并且使用 std::shared_ptr 将解决您的问题。 但如果动态分配不可接受,您可以尝试避免使用指针并使用移动语义优化复制(What is move semantics?)

【讨论】:

    猜你喜欢
    • 2012-12-28
    • 1970-01-01
    • 1970-01-01
    • 2018-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-28
    相关资源
    最近更新 更多