C ++悬空指针和内存泄漏

时间:2019-01-25 00:01:05

标签: c++ pointers memory-leaks

我很难理解如何区分悬空指针和内存泄漏。我对最近的作业有一些疑问,这使我感到困惑,读完它后,我仍然感到困惑。我不希望有人替我做家庭作业,我想能够理解为什么是什么,如果那是有道理的。

因此,作业:


给出声明:

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;
}

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

4 个答案:

答案 0 :(得分:10)

游戏规则:

  • 为每个new Type画一个方框。在框中输入一个问题(您不知道里面有什么)。
  • 对于每个delete p,请删除p所指的框。
  • 对于每个a = b(没有星星),从变量a到方框b划一条线。
  • *x = y所指的框中,每yx
  • 对于每个*x = *y,请阅读框y的内容,然后将副本放入x

结果:

  • 当您有一个没有任何变量指向它的盒子时,就会泄漏。
  • 如果您的指针没有指向一个盒子(或一个划线的盒子),那么您将有一个悬空的指针。

第一个问题:

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

让我们逐行执行此操作:

  

ptrA =新的int;

// 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 ----     *********
              *   ?   *
              *********

似乎您的盒子漏了。也就是说,有一个没有变量指向的盒子。

答案 1 :(得分:0)

  
      
  1. 我猜这很好,因为ptrA已经指向内存中的某物,所以这既不是悬空的指针也不是内存泄漏。
  2.   

是的,但是现在ptrB也指向它,而且您也无法释放ptrB之前指向的内容。

那是一个泄漏。

  
      
  1. 我猜想这是一个悬空指针,因为345是从内存中释放的,所以ptrB指向空。
  2.   

正确。

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

不,它为<ptrB所指向的事物>提供<ptrA所指向的事物>的值。无需更改所涉及的指针,只需分配int

  
      
  1. 像上一个问题一样,我不确定指向指针的含义是什么,或者我什至不知道这将达到什么目的。
  2.   

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

  
      
  1. 我知道这是一个悬空的指针,但是我不知道为什么。是因为指针指向的是函数完成后超出范围的局部变量?
  2.   

是的

答案 2 :(得分:0)

为防止进行所有作业,您的第一个假设是错误的。

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 :(得分:0)

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

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

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

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是一个局部变量,一旦函数结束,它将终止。因此,任何指向该局部变量的指针都会导致未定义的行为。所以,悬空指针!