Oops! 我无法销毁我创建的类了!

如题,我用 c++ 按照如下代码创建了一个简单的类:

struct Sth {
  int a;
  int b;
  Sth();
};
Sth::Sth() {
  a = b = 0;
}

可我试图创建再销毁这个类创建的一个实例时:

int main() {
  Sth sth;
  delete &sth;  // ERROR!!!
  return 0;
}

它报告了错误:

/home/was/cpp/a.cpp: 在函数‘int main()’中:
/home/was/cpp/a.cpp:8:11: 警告:‘void operator delete(void*, long unsigned int)’ called on unallocated object ‘sth’ [-Wfree-nonheap-object]
    8 |   delete &sth;
      |           ^~~
/home/was/cpp/a.cpp:7:7: 附注:在此声明
    7 |   Sth sth = *(new Sth);
      |       ^~~
munmap_chunk(): invalid pointer

为什么指针无效呢?

写法有点奇葩,不能用正常写法么

1 个赞

这个其实是我在写数据结构时发现的一个问题。这是我从我的数据结构代码中浓缩的,所以呈现出的比较奇葩

现在改了一下

你这个写法,明显是内存 leak 了。。。。

先在堆上分配一个 Sth 对象,然后复制给栈上一个对象。。

然后想要delete栈上的一个对象

1 个赞

那么有什么办法去delete堆上的对象吗 (在不更改实例的创建方法的情况下)

int main() {
  Sth *sth=new Sth{};
  delete sth;
  return 0;
}
2 个赞

你这是 automatic,为啥要手动 delete 呢?

这种写法好像不容易应用于数据结构中

谢谢!

写数据结构的destroy()时发现的

我也不想手动销毁呀😭

Sth 的 destructor 会在退出 main () 时自动调用,不需要手动 destroy。

1 个赞

仔细看您的贴子,再看看7楼,顿悟:

我在 我写的数据结构中 用new手动建立在堆上的东西 都在clear()方法中删除了,而automatic的会自动销毁

所以我好像不需要写destroy()了!这个问题不用去管了!「欣喜若狂」「万分感激」

代码有两个问题

1 delete不是简单的语义上释放内存,他只能用于new返回的堆内存。堆内存有自己的数据结构,delete会根据传递的指针,按照chunk的数据结构对字段做检查,包括确定回收的范围等。这也是报错的原因

called on unallocated object ‘sth’ 

delete检查给定的指针,结果发现对应的字段偏移显示这个内存还未分配,你尝试delete一个未分配的内存,所以报错(不过如果你能在栈上手动构造好堆的chunk结构,是可以不报错的),不过这些细节一般不玩二进制安全是用不到的。感兴趣可以github看下https://github.com/shellphish/how2heap这个项目。

2 你这里创建的sth对象在栈上,main函数返回时会销毁这个对象,你手动再释放肯定出问题,语义上双重释放了(虽然你这里用的delete不会成功)。

1 个赞