C++ 是否保证在成功解除分配后分配内存?

Does C++ guarantee a memory allocation after a successful deallocation?

提问人:Sourav Kannantha B 提问时间:7/24/2023 更新时间:7/24/2023 访问量:90

问:

请看这个例子,

// x is a int* allocated previously via 'new'
delete x;
x = new int;

此代码是否始终保证最后一行的内存分配,因为至少从上一次释放中肯定还剩下内存来保存 int。

如果该标准目前没有提供任何此类保证,那么该决定是否因为潜在的优化空间?

是否有任何流行的实现利用了该优化,或者所有这些实现都只是保证了解除分配后的分配?

还是根本无法提供这样的保证?在这种情况下,您能否提供一个案例,说明解除分配后的分配绝对注定会失败。

当我在上面的问题中说解除分配后的分配时,我说的是与解除分配大小相等或更小的分配,因为我知道由于内存不足,分配更大的大小可能并不总是可行的。

C++ 管理 动态内存分配 删除运算符

评论

1赞 pptaszni 7/24/2023
欺骗 stackoverflow.com/a/6624123/4165552
3赞 Quimby 7/24/2023
当然不是,您可以让运算符过载,每次都会抛硬币,决定它是否会立即失败或尝试处理您的请求。new
3赞 freakish 7/24/2023
“肯定还有记忆可以容纳一个 int”是什么让你这么认为?首先:你甚至不知道你使用什么分配器,因为这些分配器可以动态切换。此外:你认为你的过程是你的机器上唯一运行的东西吗?绝对没有办法保证这样的事情,除非你使用自定义的、手写的分配器,完全由你控制。
3赞 heap underrun 7/24/2023
内存是一种共享资源。谁能保证在调用 和 之间,其他一些进程没有分配内存,导致可用内存耗尽?好吧,单身真的是一个非常小的分配量,这样的情况不太可能发生。但是,如果你谈论的是一般情况,例如,一个多兆字节的向量,那么就更容易理解为什么不可能提供这样的保证。deletenewint
1赞 freakish 7/24/2023
@SouravKannanthaB这不是我所说的“动态切换”的意思。我的意思是,您只需使用 env 变量即可使用不同的分配器运行已编译LD_PRELOAD二进制文件。至少在 Linux 下。因此,您可以使用任何分配器运行代码,而无需重新编译。而分配器所做的是分配器本身的实现细节,你无法控制它。并且没有标准来强制执行此类行为。

答:

4赞 Alan Birtles 7/24/2023 #1

不能保证你会得到一个新的内存位置,事实上,该标准没有提供任何关于内存分配如何工作的细节,返回一个指向新对象的指针,这就是标准所说的全部内容。在某些实现中,您甚至可能会发现您的代码总是生成相同的对象,并且根据标准,这没有任何违法行为。new

https://en.cppreference.com/w/cpp/language/new

在语言行为对用户不重要的地方,为了不限制实现者,故意不指定标准。例如,在内存分配的情况下,可以使用堆来实现,使用固定大小的预分配内存池,或者甚至可以为每个对象大小提供单独的内存块池。new

评论

0赞 Sourav Kannantha B 7/24/2023
假设 new 是使用 或 实现为系统调用的。那么,该实现是否可以保证在解除分配后进行分配?sbrkmmap/munmap
1赞 Ted Lyngmo 7/24/2023
@SouravKannanthaB 否
1赞 freakish 7/24/2023
@SouravKannanthaB内存分配器的作用远不止一些系统调用。事实上,它们倾向于最大限度地减少系统调用的数量。我说的是马洛克。此外,我们可以在运行时动态切换 malloc 实现,例如从 libc 切换到 jemalloc。绝对没有办法保证你想要什么。
1赞 j6t 7/24/2023
问题不在于返回的位置是否是“新的”(即,与先前的分配不同),而在于分配是否首先成功。