【问题标题】:Identifying memory management issues识别内存管理问题
【发布时间】:2022-01-07 07:10:40
【问题描述】:
#include "A.h"
int main (int argc, char*argv[]){
A * p_a1 = new A();
A * p_a2 = p_a1;
delete p_a1;
p_a1 = 0;
delete p_a2 <br>

A 是某个类的这段代码会导致内存管理问题吗?
我的想法:
第一行将创建一个指向 A 的指针。我不确定这是否也会为 A 分配内存,还是只是分配一个地址?第二个指针 p_a2 指向确切的位置。
delete p_a1 将删除分配的内存,它可能没有任何 p_a1=0,使其为空。删除 p_a2。然后我们删除空指针,这可能不会影响
这会导致任何内存泄漏或问题吗?

【问题讨论】:

  • 将空值分配给p_a1p_a2 没有影响。 (了解指针最重要的一点是,指针没有什么特别之处。)
  • 一般来说,所有新的都有匹配的删除是个好主意,最好在代码附近。
  • A * p_a2 = p_a1; -- 在该行之后,p_a2 独立于 p_a1。调用delete p_a1; 不会神奇地通知p_a2 p_a1delete 调用它。确保所有指向该对象的指针都得到通知的所有工作在 C++ 中不存在开箱即用的情况——您必须以某种方式自己维护它,这使得内存管理在许多情况下容易出错案例。如果你想真正共享指向同一个对象的指针,C++ 中有一个叫做std::shared_ptr 的东西可以完成所有这些工作。
  • 答案是:1) 是的。 2) 从动态存储中为 A 分配内存构造 A。3) 不正确,删除悬空指针是 未定义的行为。 4) 是的,它会导致未定义的行为(称为“问题”)。

标签: c++ pointers memory


【解决方案1】:

两次删除同一个对象肯定是内存管理问题。 delete p_a1; 确实删除了p_a1 指向的对象,然后delete p_a2 尝试删除同一个对象。

记住:你不是在删除指针,而是在删除它们指向的对象。

原始new 始终是代码异味和潜在的错误来源。您的代码应如下所示:

#include "A.h"
int main (int argc, char*argv[]){
   A a;
}

坦率地说,考虑到您的问题,恕我直言,人们要么只能触及表面,要么写一篇长文来解释重要的基础知识。我选择了第一个,并为您推荐一本书以了解更多详细信息:The Definitive C++ Book Guide and List

【讨论】:

    【解决方案2】:

    您的问题是 p_a1p_a2 是独立的指针,一次恰好指向同一个对象。

    之后

    delete p_a1;
    p_a1 = 0;
    

    p_a1 的角度来看,一切都很好:它指向的对象已被删除,并且指针本身收到了nullptr 值,因此现在可以安全地再次执行delete p_a1

    但是p_a2 没有改变,现在指向一个已经到了生命尽头的对象。所以它变成了一个 悬空 指针,取消引用或删除它会调用 UB。

    如果您希望 p_a2p_a1等效,您应该将其作为参考:

    A* &p_a2 = p_a1;
    

    现在在p_a1 = 0 之后,p_a2 是对空指针的引用,可以安全地删除它。

    【讨论】:

    • 所以我的理解是因为 p_a2 指向的内存在我们执行delete p_a1 时已被释放,所以现在 p_a2 指向的内存地址可能实际上不属于程序,甚至可能这样会导致问题吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-23
    • 2011-01-07
    • 2016-10-20
    • 2011-04-11
    相关资源
    最近更新 更多