访问已销毁的对象不会导致segfault



出于好玩,我决定看看gdb会怎么评价这段代码,这段代码旨在尝试使用已经销毁的对象的方法。

#include <iostream>
class ToDestroy
{
public:
  ToDestroy() { }
  ~ToDestroy() {
    std::cout << "Destroyed!" << std::endl;
  }
  void print() {
    std::cout << "Hello!" << std::endl;
  }
};
class Good
{
public:
  Good() { }
  ~Good() { }
  void setD(ToDestroy* p) {
    mD = p;
  }
  void useD() {
    mD->print();
  }
private:
  ToDestroy* mD;
};
int main() {
  Good g;
  {
    ToDestroy d;
    g.setD(&d);
  }
  g.useD();
  return 0;
}

输出为(使用-O0标志构建):

被摧毁了!

你好!

在堆中分配d并删除它会导致相同的行为(即,没有崩溃)。

我认为内存没有被覆盖,C++被"欺骗"而正常使用它。然而,我感到惊讶的是,在对堆进行分配和删除时,可以使用未分配给它们的内存。

有人能对此提供更多见解吗?这是否意味着,当试图取消引用指针时,如果该内存恰好对我们的上下文具有"连贯性",则尽管内存没有分配给我们,但执行不会导致SEGFAULT?

当您试图访问操作系统禁止您访问的地址时,会发生segfault。这可能是因为地址后面的内存没有分配给您的进程,也可能是因为它不存在或其他原因。因此,您现在正试图访问一段仍分配给进程的内存,因此没有segfault。

Malloc(管理堆的那个)使用某些缓冲区来限制系统调用的数量。因此,您可以访问未初始化的内存。

您向print传递了一个无效的this指针,但它从未被取消引用,因为print不是虚拟的,也没有访问任何成员。

相关内容

  • 没有找到相关文章

最新更新