【问题标题】:Accessing pointers after deletion [duplicate]删除后访问指针[重复]
【发布时间】:2019-05-06 16:02:39
【问题描述】:

我有一个如下所示的代码 sn-p。我为我的Something 类创建了一些动态内存分配,然后将它们删除。 代码打印出我期望的错误数据,但为什么->show 不会崩溃? 在什么情况下/如何->show 会导致崩溃? 是否可以用其他对象覆盖 i、ii、iii 的相同内存位置?

我试图理解为什么在delete 释放了要写入其他内容的内存位置之后仍然有关于->show 的信息!

#include <iostream>
#include <vector>

class Something
{
public:

  Something(int i) : i(i)
  {
    std::cout << "+" << i << std::endl;
  }

  ~Something()
  {
    std::cout << "~" << i << std::endl;
  }

  void show()
  {
    std::cout << i << std::endl;
  }
private:
  int i;

};

int main()
{
  std::vector<Something *> somethings;

  Something *i = new Something(1);
  Something *ii = new Something(2);
  Something *iii = new Something(3);

  somethings.push_back(i);
  somethings.push_back(ii);
  somethings.push_back(iii);

  delete i;
  delete ii;
  delete iii;

  std::vector<Something *>::iterator n;
  for(n = somethings.begin(); n != somethings.end(); ++n)
  {
    (*n)->show(); // In what case this line would crash? 
  }

  return 0;
}

【问题讨论】:

  • 未定义的行为不一定会导致崩溃。它的行为是……嗯,未定义。
  • ASan 变成crash
  • @PMoubed -- 我得问一下 -- 你为什么似乎试图让程序崩溃?是不是因为您使用指针编写了一些其他代码,而您对代码的可靠性没有信心,并希望“崩溃”可以帮助您找到错误?如果是这种情况,我很遗憾地说 C++ 不能这样工作。
  • 当涉及未定义的行为时,通过示例/实验学习效果不佳。实验需要一致的结果来学习。未定义的行为不一致。
  • 我认为您的部分问题是为什么有关-&gt;show() 的信息没有丢失。您的方法在编译时解决。将其声明为 virtual 将使其在运行时从对象本身解析。但是除非你真的用一些东西覆盖了这个对象,否则你甚至不能保证它会立即崩溃。

标签: c++


【解决方案1】:

代码打印出我期望但why -&gt;show 没有崩溃的错误数据?

为什么你同时期望数据是错误的,但又会崩溃?

通过无效指针间接的行为是未定义的。期望数据是正确的、期望数据是错误的、期望它崩溃、也不期望它不崩溃是不合理的——尤其是。

-&gt;show 在什么情况下/如何导致崩溃?

C++ 语言没有指定程序崩溃的情况。崩溃是 C++ 特定实现的一个细节。

例如,如果您尝试写入标记为只读的内存区域或尝试访问未映射的内存区域,Linux 系统通常会由于“分段错误”而强制进程崩溃。

在标准 C++ 中没有直接的方法来创建内存映射:语言实现负责为您创建的对象映射内存。

这是一个在特定系统上demonstrably crashes 的程序示例:

int main() {
    int* i = nullptr;
    *i = 42;
}

但 C++ 不保证它会崩溃。

是否可以用其他对象覆盖 i、ii、iii 的相同内存位置?

行为未定义。就语言而言,一切皆有可能。

【讨论】:

  • 所以我在show 中添加了virtual 关键字,导致分段错误。
  • @PMoubed 好的。请记住,不能保证会导致分段错误。就像没有虚拟就不能保证不会导致分段错误。
  • 我错过了所有 cmets 和答案中的“未定义行为”、“不保证”这一点。现在我知道了!
【解决方案2】:

请记住,指针存储一个整数内存地址。在调用delete 时,动态内存将被释放,但指针仍将存储内存地址。如果我们将指针清空,那么程序就会崩溃。

看到这个问题:What happens to the pointer itself after delete?

【讨论】:

  • 不保证程序会崩溃,即使指针为空。它仍然是 UB。
  • 我尝试在每次删除后将指针清空,但结果相同 - 没有崩溃!
  • @super 就在这里。我们不能确定它会崩溃,因为这是未定义的行为。我们可以说它可能会崩溃,因为访问已删除的指针是个坏主意。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-10
相关资源
最近更新 更多