C++悬而未决的指针和内存泄漏

C++ Dangling Pointers and Memory Leaks

本文关键字:内存 泄漏 指针 悬而未决 C++      更新时间:2023-10-16

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

所以,作业:


鉴于声明:

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

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

游戏规则:

  • new Type画一个盒子。在盒子里放一个问题(你不知道里面有什么)。
  • 对于每个delete p划掉p指向的框。
  • 对于每个a = b(没有星星的地方),画一条从可变a到框b的线。
  • 对于每个*x = y,在x指向的框中写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 ----     *********
*   ?   *
*********

似乎你有一个泄漏的盒子。 即有一个没有变量指向它的框。

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

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

所以这是一个泄漏。

  1. 我猜这是一个悬而未决的指针,因为 345 是从内存中释放的,所以 ptrB 什么都不指向。

正确。

  1. 最后一行是否表示指针指向另一个指针?

不,它赋予<ptrB指向的东西><ptrA指向的东西>的价值。不更改所涉及的指针,仅int分配。

  1. 像上一个问题一样,我不确定指向指针是什么意思,或者我什至不明白这是什么目的。

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

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

是的。

为了防止做所有的家庭作业,你的第一个假设是错误的。

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, [ ? ]

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

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

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