Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
由于内存原因导致realloc失败时如何处理?_C_Memory_Realloc - Fatal编程技术网

由于内存原因导致realloc失败时如何处理?

由于内存原因导致realloc失败时如何处理?,c,memory,realloc,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->ma

问题说明了一切,但这里有一个例子:

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;
}
我如何处理内存不足而不清空所有数据


编辑-假设可以做一些事情,例如,在某个地方释放一些内存,或者至少告诉用户“你不能那样做-你的内存不足”。理想情况下,我想把分配的内容留在那里。

这是一个热门话题,因为在这个问题上,基本上有两个学派

  • 检测OOM,并让函数返回错误代码
  • 检测OOM并尽快使进程崩溃
  • 就我个人而言,我在第二营地。除了非常特殊的应用程序类型外,OOM是一个致命的周期。诚然,写得完美的代码可以处理OOM,但是很少有人知道如何在没有内存的情况下编写安全的代码。更不用说真正去做了,因为这几乎不值得付出努力


    我不喜欢将错误代码传递给OOM的调用函数,因为这相当于告诉调用方“我失败了,您对此无能为力”。相反,我更喜欢快速崩溃,以使生成的转储尽可能具有指导意义

    那完全是你的问题!以下是一些标准:

    • 你要求记忆是有原因的。如果它不可用,您的程序的工作是注定要失败的还是可以继续工作?如果是前者,您希望用错误消息终止您的程序;否则,您可以以某种方式显示错误消息并继续

    • 有没有可能用时间换取空间?你能用一种占用更少内存的算法回答你尝试的任何操作吗?这听起来像是一个很大的工作,但实际上是一个可能性,继续您的程序的运作,尽管最初没有足够的内存

    • 如果没有这些数据,没有足够的内存,你的程序继续蹒跚前行,这是错误的吗?如果是这样,您应该以错误消息终止。终止程序比盲目地继续处理错误数据要好得多


      • 标准技术是引入一个新变量来保存realloc的返回。然后,只有在输入变量成功时才覆盖它:

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

        使用
        realloc
        时应遵循的第一条规则是不要将
        realloc
        的返回值分配给传递给它的同一个指针。这个

        m->data = realloc(m->data, m->max * sizeof(void*)); 
        
        这很糟糕。如果
        realloc
        失败,它将返回空指针,但不会释放旧内存。上述代码将使您的
        m->data
        无效,而以前由
        m->data
        指向的旧内存块很可能会成为内存泄漏(如果您没有其他引用)

        realloc
        的返回值应首先存储在单独的指针中

        void **new_data;
        ...
        new_data = realloc(m->data, m->max * sizeof(void*)); 
        
        然后,您可以检查成功/失败,并在成功的情况下更改
        m->data
        的值

        if (new_data != NULL)
          m->data = new_data;
        else
          /* whatever */;
        

        还有另一个来自realloc的微妙错误。来自返回的空指针的内存泄漏是众所周知的(但很难偶然发现)。 在我的程序中,偶尔会有一次来自realloc调用的崩溃。我有一个动态结构,它可以自动调整大小,并使用类似于此的realloc:

        m->data = realloc(m->data, m->max * sizeof(void*)); 
        
        我犯的错误是没有检查m->max==0,这释放了内存区域。并使我的m->数据指针变为陈旧的指针

        我知道这有点离题,但这是我和realloc之间唯一的真正问题

      • 了解应用程序框架如何处理OOM。许多人根本不会处理OOM。大多数情况下,一个框架在没有空闲RAM的情况下无法正常运行,除非它在某个地方非常明确地说它会正常运行。如果框架不能处理OOM并且是多线程的(现在很多),OOM在很多情况下都将是该过程的结束。即使它不是多线程的,也可能接近崩溃。您是否退出流程或框架可能是一个没有意义的问题;在不久的将来,可预测的立即退出可能比在某个半随机点崩溃要好一点

      • 如果您使用一个单独的专用子内存池(即不是通常的malloc)来执行一组定义良好的操作,这些操作只受OOM的内存使用限制(即当前操作在OOM上被回滚或完全中止,用于子内存池,而不是整个进程或主内存池),应用程序框架也不使用该子池,或者如果您的框架和整个应用程序的其余部分被设计为在没有空闲RAM的情况下保持有意义的状态和持续运行(在内核模式和某些类型的系统编程中很少见但并非闻所未闻)返回错误代码而不是使进程崩溃可能是正确的

      • 理想情况下,一段处理的大部分内存分配(或更理想的是所有分配)应在处理过程中尽快分配,最好是在正确开始之前,以最大限度地减少数据完整性丢失问题和/或失败时所需的回滚编码量。实际上,很多时候,为了节省项目的编程成本和时间,为了保持数据完整性,应用程序依赖于数据库事务,需要用户/支持人员检测GUI崩溃(或服务器崩溃),并在出现内存不足错误时重新启动应用程序,而不是以最好的方式处理和回退任何和所有数千种潜在的OOM情况。然后,努力将重点放在限制应用程序在过载情况下的暴露,这可能包括额外的验证和对数据大小以及同时连接和查询的限制

      • 即使您检查有多少内存被报告为可用,通常其他代码也会尽可能地分配或释放内存
            void* temp = realloc(m->data, m->max * sizeof(void*));
            if (m->max!=0&&temp==NULL) { /* crash or return error */ }
            m->data =(void**)temp;
        
        a = realloc(a, size);
        
        tmp = realloc(a, size);
        if (tmp)
            a = tmp;
        else
            /* handle error */