-1

我知道 C++ 允许创建一个带有已删除或不可访问的析构函数的类:

struct Foo{
    Foo() = default;
    ~Foo() = delete;
};

Foo f;// error: ~Foo is deleted
Foo* pf = new Foo();// ok
  • 现在可以创建一个动态对象,但它会泄漏。

  • 我们知道我不应该delete使用 withfreenewwithmalloc但我们可以将任何类型的指针转​​换为指向的指针void

    无效* p = (无效*)pf; 免费(p);

  • 现在可以安全地释放pfvia指向的动态对象,free然后再转换为void*?

  • 如果它不安全,那么如果我的类已删除dtor,则无法释放在免费商店中分配的对象?

4

2 回答 2

2

您可以 malloc 内存,放置新内存,然后释放内存。

这结束了对象的生命周期而不破坏它。子对象的生命周期也结束了,但它们的析构函数也没有被调用。这可能是危险的,或者如预期的那样。

您不能释放由 new 分配的内存。这样做是 C++ 标准未定义的行为。

理论上,您可以在类上重载 operator new 以调用 malloc 然后放置 new 对象。这将使免费通话更加行为良好。

于 2021-10-12T16:55:27.930 回答
2

不。

这与类型无关void*,而与分配器设计有关。

new并且malloc可能工作方式完全不同,甚至可能不共享相同的内存。因此,您不允许将一个发送到另一个是合乎逻辑的。

另外,即使你打电话free,你也需要打电话~Foo()。否则,您仍然会泄漏对象。

GCC 甚至有礼貌地警告你:

<source>: In function 'int main()':
<source>:10:9: warning: 'void free(void*)' called on pointer returned from a mismatched allocation function [-Wmismatched-new-delete]
   10 |     free(pf);
      |     ~~~~^~~~
<source>:9:23: note: returned from 'void* operator new(long unsigned int)'
    9 |     Foo* pf = new Foo();// ok
      |                       ^

然后你可能会尝试运行程序,但地址清理程序会报告错误并中止程序:

=================================================================
==1==ERROR: AddressSanitizer: alloc-dealloc-mismatch (operator new vs free) on 0x602000000010
    #0 0x7fa4139b04f7 in free (/opt/compiler-explorer/gcc-11.2.0/lib64/libasan.so.6+0xb14f7)
    #1 0x401177 in main /app/example.cpp:10
    #2 0x7fa4133b60b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
    #3 0x40109d in _start (/app/output.s+0x40109d)

0x602000000010 is located 0 bytes inside of 1-byte region [0x602000000010,0x602000000011)
allocated by thread T0 here:
    #0 0x7fa4139b1f57 in operator new(unsigned long) (/opt/compiler-explorer/gcc-11.2.0/lib64/libasan.so.6+0xb2f57)
    #1 0x401167 in main /app/example.cpp:9
    #2 0x7fa4133b60b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)

SUMMARY: AddressSanitizer: alloc-dealloc-mismatch (/opt/compiler-explorer/gcc-11.2.0/lib64/libasan.so.6+0xb14f7) in free
==1==HINT: if you don't care about these errors you may set ASAN_OPTIONS=alloc_dealloc_mismatch=0
==1==ABORTING

具有已删除析构函数的对象并不意味着是自由的,或者以任何常规方式实例化。


但是,您可以分配一块内存,将 new 放入其中,然后在释放该内存块时销毁所有子对象(包括基类)。

于 2021-10-12T16:57:10.863 回答