在C++中,一个线程使用new分配的内存可以被另一个线程删除吗?

11

在glibc中,malloc是使用arenas实现的。例如,由线程A首先分配并稍后由free释放的内存可能无法被线程B中的另一个malloc调用使用,因为线程A和B可能在不同的arenas中,并且不同的arenas维护内存的不同堆和空闲列表。

当涉及到C++(也许还包括C++11,因为C++11有一个新标准),情况是否仍然相同?

或者不同的线程实际上共享相同的堆段和内存的空闲列表,而一个线程中的new可以分配另一个线程中首先new然后delete的内存吗?

如果答案取决于实现,则问题是如何在主要的C++编译器中实现,例如g ++,MVC ++,icc?

编辑

我认为这个问题是有意义的,因为有时候你会启动很多线程,在每个线程中动态分配/释放大块内存来存储大量对象,而你不希望应用程序的内存使用量过高。


1
C++并没有规定如何实现分配函数,它只规定了它们必须产生什么结果。 - Kerrek SB
2
不要为C++问题添加C标签! - too honest for this site
在Linux上,如果您为大量对象分配/释放大块内存,并且这个“大”确实很大,它将使用专用的内存映射区域,然后返回给操作系统。对于小型分配:它们将位于区域中,但往往会平均分配。通过虚拟内存和交换,这很少是一个实际问题(特别是对于64位应用程序)。我的建议是:继续编码,如果它真正出现了再去担心它。 - Tony Delroy
你或许应该明确指定并标记更精确的环境,和/或声明你想知道语言标准是否对此有任何要求。 - hyde
我猜你的问题是:如果在线程1中分配了500MB的小对象,然后从线程2中释放它们,接着在线程1中再次分配500MB,那么它是否会重用刚刚释放的内存?是这样吗? - user253751
显示剩余5条评论
3个回答

2

这段文字的意思是:

不同的线程实际上共享堆内存和空闲内存列表,一个线程中的new操作可能会先分配内存,后面被另一个线程删除。

线程的目的是共享内存空间。如果您不需要此功能,则最好使用进程。


请注意,在 C 语言中,某个线程可以访问的自由内存空间可能对另一个线程不可访问。我询问的是 C++ 中的行为,我并不是在谈论跨不同线程访问变量之类的事情。 - Allanqunzi
@Allanqunzi - 如果是这种情况,那就不需要使用线程了,因为它们与进程相比的主要优点是更容易的内部通信。 - Martin James
@Allanqunzi “某个线程可以访问的空闲内存空间可能对另一个线程不可访问。” 在哪里?在什么情况下? - curiousguy

1
C++标准和您使用的分配器实现是两个不同的东西。如果您使用gcc编译C++代码,则默认使用glibc作为分配器。因此,如果您的gcc版本足够新,则使用具有每个线程区域的glibc,您就可以开始了。

0

这取决于具体情况。在Windows上,使用DLL的线程不允许将在一个DLL中分配的内存所有权转移到另一个DLL中。所有的new和delete操作必须在同一侧的DLL中执行。虽然这不是严格的线程问题,但它仍然意味着一个线程不能简单地将内存所有权转移给任何其他线程,而不知道内存的起源。

请参见静态链接DLL是否使用与主程序不同的堆?


2
不存在所谓的“基于DLL的线程”。在DLL中通过“new”分配的内存不能通过其他DLL或主应用程序中的“delete”进行释放-这与线程无关。 - user253751
我将措辞从“基于DLL的线程”更改为“使用DLL的线程”,因为这才是我的意思。 - Mark Lakata
如果使用相同的编译器和标志编译DLL,则释放在另一个DLL中分配的内存不会有问题。 - user2672107

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接