对运算符的调用是否'delete'同步的?

Is the call to operator 'delete' synchronous?

本文关键字:同步 delete 运算符 调用 是否      更新时间:2023-10-16

我想知道对操作符delete的调用是否同步。换句话说,如果我这样做:

delete p;

c++标准是否保证只有在调用完成执行后内存才会被释放?或者调用是异步的,只是为操作系统调度一个任务,以便在它决定释放内存的最佳时机时立即释放内存?

如果第一种情况是有效的,那么是否意味着我们必须实现我们自己的异步删除工具?我问这个问题是因为我想说,大多数时候我们(程序员)并不关心内存何时被释放,因此我们不希望我们的代码冻结并等待这个(最可能昂贵的?)系统调用完成,而是安排一个删除任务并立即继续执行。c++是否提供了任何标准工具(也许是通过标准库?)来做到这一点,而无需重新发明轮子?

delete为同步。现在,这并不意味着底层内存实际上在那个时候被操作系统释放了,但是从c++系统的角度来看,它的行为就像。

我问这个问题是因为我想说大多数时候我们(程序员)并不关心内存何时被释放

但是delete主要不是关于内存的,它只是以确定性的方式调用析构函数——它是一种通用的资源释放机制,不局限于内存。在这里,具有同步性是很重要的,否则c++的一个核心方面——RAII——将无法工作。

不能保证delete p;将内存释放回操作系统——永远不能。事实上,在相当多的(大多数?)实现中,它不会做任何这样的事情。

当您调用delete时,究竟发生了多少,但在某些情况下,它几乎是即时的(只是将块链接到空闲内存块列表)。在其他情况下,它做了更多的工作:销毁对象,可能还在当前空闲列表中搜索可以与被释放的块合并的相邻块。

就您所关心的而言,一切都完全按照您的期望运行,并且没有隐藏的陷阱或陷阱。你总是可以说T * p = new T; delete p;,这是正确的,无论在什么上下文中。

考虑到操作系统通常必须并发地为各种进程和线程分配内存,您可以假设这个问题已经被正确地解决了。

更正式地说,18.6.1.4/1 ("Data Races")说:

为了确定是否存在数据竞争,operator new的库版本,全局operator new的用户替换版本,以及C标准库函数callocmalloc应该表现得好像它们只访问和修改了返回值所引用的存储。库版本operator delete的,operator delete的用户替换版本,以及C标准库函数free的行为应该表现得好像它们只访问和修改了它们的第一个参数所引用的存储。

关于"阻塞":这一切都归结为C库的分配函数所做的。除了"此函数返回指向某些内存的指针"之外,没有指定任何内容。这取决于平台如何提供内存分配。

C/c++中的自由调用已经非常快了。在这方面,你没有理由拖延到更合适的时候才删除它。你为此需要做的任何簿记都将超过实际的免费通话时间。

如果你的析构函数做更多的工作,比如关闭DB连接的套接字,那么你可以在以后的时间做这种工作,但这应该是一种例外情况。