我可以确定重新分配更少的内存总能找到足够的内存吗?

Posted

技术标签:

【中文标题】我可以确定重新分配更少的内存总能找到足够的内存吗?【英文标题】:Can I be sure that reallocating less memory will always find enough of it? 【发布时间】:2021-11-06 22:17:57 【问题描述】:

假设我只有malloced x 字节的内存,在对它们做了一些事情之后,我想realloc y < x 字节。我可以做到这一点,同时确保我的realloc 会找到足够的内存吗?例如,

int *p = malloc(10);
if (p != NULL) 
    // Do something with `p`.
    int *p_ = realloc(p, 5);
    // Keep doing something else.

我是否应该确保p_ 不是NULL,即使我重新分配的内存比原来的少?我认为*alloc函数在请求的内存超过可用内存时返回NULL,之前的代码可以安全使用吗?

【问题讨论】:

由于 realloc 被记录为能够失败,您当然应该始终检查返回值。它会在你的场景中失败吗? - 可能不会,但不能保证。 "我应该确保 p_ 不为 NULL"。是的你应该。为什么要冒险?它不太可能失败,但不能保证它不会。 你必须检查 NULL 【参考方案1】:

我可以确定重新分配更少的内存总能找到足够的内存吗? 我可以做到这一点,同时确保我的 realloc 会找到足够的内存吗?

不,realloc(p, 5); 可能会失败并返回 NULL


即使我重新分配的内存比原来的少,我是否应该确保 p_ 不为 NULL?

是的,代码,缩小尺寸时返回NULL,可以继续使用旧值指针 - 它仍然有效。

int *p_ = realloc(p, 5); 
if (p_) 
  p = p_;
 else /* if new_size <= old_size and new_size > 0 */ 
  ; // Simply continue with the old `p`, it is still good.

// Do something with `p`.
…
free(p);

注意:这个else 路径通常很难测试。


我认为 *alloc 函数在请求的内存超过可用内存时返回 NULL,之前的代码可以安全使用吗?

不要假设。 realloc() 可能会返回 NULL,如果新尺寸更大、相同或更小。


设计考虑:

当大小减小时在realloc() 上返回NULL 是合理的,前提是 1) 满足内存句柄 的数量(系统可能只允许这么多分配)并且calloc() 可以暂时需要另一个。 2) 新的大小为0。*alloc(0)上的返回值细节有历史,有点争议,这里不再讨论。

在任何情况下,只要新大小大于零,NULL 的返回就意味着某个资源在末尾。 Occam's razor 建议代码继续进行与 calloc() 由于大小增长而返回 NULL 时相同的错误处理。

【讨论】:

我需要针对谁的标准库提交错误?如果你因为没有竞技场手柄而无法缩小规模,请不要说你做到了。 @Joshua “我需要针对谁的标准库提交错误?” --> 没有错误。 C 规范允许返回 NULL。明确“代码......可以继续使用旧值指针”不是建议 - 只是一个编译选项。后面的“进行相同的错误处理”是。 此时这是一个兼容性约束。我见过太多假设缩小总是有效的代码。 @Joshua 这个答案并不假定收缩总是有效的。这个答案你发现兼容性限制或错误吗? 我发现大多数知道它正在缩小缓冲区的代码都不会检查并假设 realloc() 成功。为堆块(包括空闲堆块)设置单独句柄的想法是不自然的。

以上是关于我可以确定重新分配更少的内存总能找到足够的内存吗?的主要内容,如果未能解决你的问题,请参考以下文章

为啥尽管我在变量中使用 malloc 分配更多内存,但当我打印变量的大小时,它仍然显示更少的内存/字节? [复制]

在 PHP 中使用静态方法和属性会占用更少的内存吗?

为啥在这段代码中向量比指针使用更少的内存?

调用垃圾回收会导致程序在java中使用更少的堆内存

如何使用更少的内存在 collectionView 中显示照片库

如何让 MySQL 使用更少的内存?