如何在内存失败时处理realloc?

Nic*_*unt 19 c memory realloc

问题说这一切,但这里是一个例子:

typedef struct mutable_t{
    int count, max;
    void **data;
} mutable_t;


void pushMutable(mutable_t *m, void *object)
{
    if(m->count == m->max){
        m->max *= 2;
        m->data = realloc(m->data, m->max * sizeof(void*));
    }
    // how to handle oom??
    m->data[m->count++] = object;
}
Run Code Online (Sandbox Code Playgroud)

如何处理内存耗尽而不是所有数据的NULL?

编辑 - 让我们假设有些东西可以完成,比如在某处释放一些内存,或者至少告诉用户"你不能那样做 - 你的内存不足".理想情况下,我想留下那里分配的东西.

R S*_*hko 24

标准技术是引入一个新变量来保存realloc的返回值.然后,如果成功,则只覆盖输入变量:

tmp = realloc(orig, newsize);
if (tmp == NULL)
{
    // could not realloc, but orig still valid
}
else
{
    orig = tmp;
}
Run Code Online (Sandbox Code Playgroud)

  • 然后什么?您没有尝试增加数组的大小以获得乐趣,实际上您需要这样做是有原因的. (7认同)
  • @andreaconsole - 如果tmp为NULL,那么无关紧要(在所有现代malloc实现中都是`free(NULL)`).如果tmp不是NULL,那么是的,你需要释放它,但你需要在正确的时间释放它.orig = malloc(size)... tmp = realloc(orig,newsize)if(tmp == NULL){free(orig); ......放弃......}其他{orig = tmp; } ...免费(orig); (4认同)
  • @Blindy - 失败了.根据应用程序的逻辑,由它决定如何恢复(可能这是一个服务器,它将使一个请求失败,但继续运行其他请求).但这看起来像低级库代码,不应该强制应用程序的内存不足策略. (2认同)

Alo*_*hal 8

realloc()失败时应采取的措施取决于您的申请.这个问题过于笼统,无法回答所有可能的情况.

其他一些说明:

永远不会做:

a = realloc(a, size);
Run Code Online (Sandbox Code Playgroud)

如果realloc()失败,则会丢失原始指针,而realloc()不是free()原始内存,因此会出现内存泄漏.相反,做:

tmp = realloc(a, size);
if (tmp)
    a = tmp;
else
    /* handle error */
Run Code Online (Sandbox Code Playgroud)

我要做的第二点是次要的,可能不是那么重要,但无论如何都要了解它是很好的:增加由一个因子分配的内存f是好的.我们先说malloc() n个字节.然后你需要更多的内存,所以你realloc()的大小为n×f.那么你需要更多的内存,所以你需要n×f 2个字节.如果你想realloc()从前面的两个内存块使用空间,你要确保Ñ×F 2 ≤N + N×F .求解该等式,得到f≤(sqrt(5)+1)/ 2 = 1.618(黄金比率).我1.5大多数时候使用的因素.


Jar*_*Par 7

这是一个热点按钮主题,因为在这个主题上基本上有两种思想流派

  1. 检测OOM,并使该函数返回错误代码.
  2. 检测OOM并尽快崩溃您的进程

我个人在营地#2.对于非常特殊类型的应用程序,OOM是致命期.确实,完美编写的代码可以处理OOM,但很少有人理解如何编写在没有内存的情况下安全的代码.实际上做的更少,因为它几乎不值得付出努力.

我不喜欢将错误代码传递给OOM的调用函数,因为它相当于告诉调用者"我失败了,你无能为力".相反,我更喜欢快速崩溃,因此产生的转储尽可能具有指导性.