【问题标题】:C++ Dangling Pointers and Memory LeaksC++ 悬空指针和内存泄漏
【发布时间】:2019-06-18 19:27:57
【问题描述】:

我很难理解如何区分悬空指针和内存泄漏。我最近的一个作业有几个问题让我感到困惑,读完之后我仍然感到困惑。我不希望有人为我做作业,我希望能够理解为什么某件事是这样的,如果这有意义的话。

所以,作业:


鉴于声明:

int *ptrA, *ptrB;

判断下面的每个代码段是否导致内存泄漏、悬空指针或两者都没有。画图帮忙。

  1. 我猜这很好,因为ptrA 已经指向内存中的某些内容,所以这个既不是悬空指针也不是内存泄漏。
ptrA = new int;
ptrB = new int;
*ptrA = 345;
ptrB = ptrA;
  1. 我猜这是一个悬空指针,因为 345 已从内存中释放,所以 ptrB 指向任何内容。
ptrA = new int;
*ptrA = 345;
ptrB = ptrA;
delete ptrA;
  1. 这是我完全迷路的地方。最后一行是否意味着指针指向另一个指针?不确定这会产生什么影响。
ptrA = new int;
ptrB = new int;
*ptrA = 345;
*ptrB = *ptrA;
  1. 与上一个问题一样,我不确定指向指针是什么意思,或者我是否明白这样做的目的。
ptrA = new int;
ptrB = new int;
*ptrA = 345;
ptrB = new int;
*ptrB = *ptrA;
  1. 我知道这是一个悬空指针,但我不知道为什么。是不是因为指针指向的局部变量在函数完成时超出了作用域?
ptrA = LocationOfAge();

其中函数LocationOfAge定义为:

int *LocationOfAge() {
  int age = 21;
  return &age;
}

感谢任何愿意提供帮助的人。

【问题讨论】:

  • 一个问题应该包含一个问题。这包含五个。它们密切相关,但你可能会推动它。 ptrB = ptrA; in 1 刚刚泄露了 ptrB。它持有的地址已经没有了,所以没有办法删除它持有的东西。
  • @user4581301 评论不应包含答案:)
  • 为每个new画一个框。对于每一个删除框(你没有那些)。对于每个a = b(没有星号的地方)画一条从变量到框的线。对于每个*x = y,在框内写上 y。当你有一个没有变量指向它的盒子时,你就有了泄漏。如果你有一个不指向盒子的指针,你就有一个悬空指针。
  • 这只是答案的 1/5。
  • 快速评论悬空指针和内存泄漏之间的区别:它们(几乎)是相反的。悬空指针指向一块已分配但已解除分配的内存。可能会重新分配给其他东西。内存泄漏是活动程序中没有指针指向的内存。 (在其他泄露的对象中可能有指向它的指针。)

标签: c++ pointers memory-leaks


【解决方案1】:
  1. 我猜这很好,因为 ptrA 已经指向内存中的某些内容,所以这既不是悬空指针也不是内存泄漏。

是的,但现在ptrB 也指向它,你无法释放ptrB 之前指向的东西。

所以这是一个泄漏。

  1. 我猜这是一个悬空指针,因为 345 已从内存中释放,因此 ptrB 指向任何内容。

正确。

  1. 最后一行是否意味着指针指向另一个指针?

不,它给了ptrB 指向的东西> ptrA 指向的东西> 的值。所涉及的指针没有变化,只有int 赋值。

  1. 与上一个问题一样,我不确定指向指针是什么意思,或者我是否理解这样做的目的。

第二个new int 被泄露,因为曾经指向它的东西(ptrB)现在指向了第三个​​new int,而前者不能再被释放。

  1. 我知道这是一个悬空指针,但我不知道为什么。是不是因为指针指向的局部变量在函数完成时超出了作用域?

是的。

【讨论】:

    【解决方案2】:

    为了避免做所有的功课,你的第一个假设是错误的。

    1. ptrA = new int;
    2. ptrB = new int;
    3. *ptrA = 345;
    4. ptrB = ptrA;
    

    在第 1 行中,ptrA 创建了一个新整数(分配了字节),在第 2 行中,ptrB 分配了字节。比3中,1中分配的内存被填满,还可以。 然而,在第 4 行,ptrB 被地址 3 覆盖,这意味着 ptrB 的原始地址不再可达。因此存在内存泄漏,因为第 2 行为整数 PtrB 分配的字节再也无法访问,因为没有指向它的指针。

    如果您使用箭头作为指针并使用带有 ?填写时用于声明和特定值。所以它看起来像:

    1. ptrA -> [  ?  ]
    2. ptrA -> [  ?  ], ptrB -> [ ? ]
    3. ptrA -> [ 345 ], ptrB -> [ ? ]
    4. ptrA -> [ 345 ] <- ptrB, [ ? ]
    

    如您所见,最后一个框 [ ? ] 没有任何指针指向它。

    【讨论】:

      【解决方案3】:

      让我们一次回答一个问题。

      ptrA = new int;
      ptrB = new int;
      *ptrA = 345;
      ptrB = ptrA;
      

      这里是内存泄漏。为什么?因为首先没有delete。其次,当您执行ptrB = ptrA; 时,实际上无法为之前ptrB 指向的对象调用delete

      ptrA = new int;
      *ptrA = 345;
      ptrB = ptrA;
      delete ptrA;
      

      这是一个悬空指针的例子。一旦在 ptrA 上调用 delete,ptrA 指向的对象就会被释放。因此,ptrB 指向行为未定义的已释放位置。所以,悬空指针!

      ptrA = new int;
      ptrB = new int;
      *ptrA = 345;
      *ptrB = *ptrA;
      

      这里,内存泄漏仅仅是因为我们没有调用delete。我们正在做的是我们正在创建分别由 ptrA 和 ptrB 指向的两个对象,并且这两个对象的值都是 345。它们仍然在堆中保留空间。但是为什么两者都有 345 的值呢?很简单。

      当你做*ptrA = 345;时,意思是ptrA指向的对象的值应该设置为345。

      你在*ptrB = *ptrA;的时候,意思是ptrB指向的对象的值应该用ptrA指向的对象的值赋值。

      这是解引用运算符的简单功能。

      ptrA = new int;
      ptrB = new int;
      *ptrA = 345;
      ptrB = new int;
      *ptrB = *ptrA;
      

      这与第一个类似。在第 2 行,ptrB 指向一个动态分配的对象。在执行第 4 行之后,ptrB 指向全新的对象。所以,没有办法释放在第 2 行分配内存的对象。所以,内存泄漏!

      int *LocationOfAge() {
          int age = 21;
          return &age;
      }
      

      这里,age 是一个局部变量,一旦函数结束就会消失。因此,任何指向该局部变量的指针都会导致未定义的行为。所以,悬空指针!

      【讨论】:

      • 从问题来看,*ptrB = *ptrA; in 3 让提问者摸不着头脑。不妨扔给他们一块骨头,并给他们一个关于取消引用运算符的快速解释。对于五个,您应该将其称为:悬空指针。
      • 哦!我们去吧。忽略最后一点。
      • @user4581301 感谢您的建议。我已经包含了你的观点。
      【解决方案4】:

      游戏规则:

      • 为每个new Type 绘制一个框。在方框里提问(你不知道里面有什么)。
      • 为每个delete p 划掉p 指向的方框。
      • 对于每个a = b(没有星号)从变量a 到一个框b 画一条线。
      • 对于每个*x = yx 指向的框内写入y
      • 对于每个*x = *y,请阅读框y 的内容并将副本放入x

      结果:

      • 如果您有一个没有指向它的变量的框,则说明存在泄漏。
      • 如果您的指针不指向框(或划掉的框),则您有一个悬空指针。

      第一个问题:

      ptrA = new int;
      ptrB = new int;
      *ptrA = 345;
      ptrB = ptrA;
      

      让我们逐行执行:

      ptrA = 新整数;

      // Part 1 has a new so draw a box
                    *********
                    *   ?   *
                    *********
      
      // Part 2 assignment to variable add a line
      ptrA -------> *********
                    *   ?   *
                    *********
      

      ptrB = 新整数;

      // Part 3 has a new so draw another box
      ptrA -------> *********
                    *   ?   *
                    *********
      
                    *********
                    *   ?   *
                    *********
      
      // Part 4 assignment to variable add a line
      
      ptrA -------> *********
                    *   ?   *
                    *********
      
      ptrB -------> *********
                    *   ?   *
                    *********
      

      *ptrA = 345;

      ptrA -------> *********
                    *  345  *
                    *********
      
      ptrB -------> *********
                    *   ?   *
                    *********
      

      ptrB = ptrA;

      ptrA -------> *********
              |     *  345  *
              |     *********
              |
      ptrB ----     *********
                    *   ?   *
                    *********
      

      好像你有一个泄露的盒子。即有一个没有变量指向它的盒子。

      【讨论】:

      • 解释得很漂亮,超级简单!
      猜你喜欢
      • 2013-10-31
      • 2015-12-15
      • 1970-01-01
      • 1970-01-01
      • 2014-09-25
      • 2014-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多