由于内存原因导致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的调用函数,因为这相当于告诉调用方“我失败了,您对此无能为力”。相反,我更喜欢快速崩溃,以使生成的转储尽可能具有指导意义 那完全是你的问题!以下是一些标准:
- 你要求记忆是有原因的。如果它不可用,您的程序的工作是注定要失败的还是可以继续工作?如果是前者,您希望用错误消息终止您的程序;否则,您可以以某种方式显示错误消息并继续
- 有没有可能用时间换取空间?你能用一种占用更少内存的算法回答你尝试的任何操作吗?这听起来像是一个很大的工作,但实际上是一个可能性,继续您的程序的运作,尽管最初没有足够的内存
- 如果没有这些数据,没有足够的内存,你的程序继续蹒跚前行,这是错误的吗?如果是这样,您应该以错误消息终止。终止程序比盲目地继续处理错误数据要好得多
- 标准技术是引入一个新变量来保存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之间唯一的真正问题
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 */