访问已经销毁的对象不会导致段错误

时间:2015-03-19 11:07:52

标签: c++ pointers segmentation-fault

出于乐趣,我决定看看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?

2 个答案:

答案 0 :(得分:2)

当您尝试访问操作系统禁止您访问的地址时,会发生段错误。这可能是因为地址后面的mem没有分配给你进程,或者因为它不存在或者其他什么。因此,您现在正在尝试访问仍分配给您的进程的内存,因此不会出现段错误。

Malloc(管理堆的那个)使用某些缓冲区来限制系统调用的数量。所以你可以访问未初始化的mem。

答案 1 :(得分:2)

您将无效的此指针传递给print,但它永远不会被取消引用,因为print不是虚拟的,也不会访问任何成员。