malloc利弊的宏包装器

时间:2015-01-21 09:02:08

标签: c macros malloc null-check

我一直在检查malloc返回的内容如下:

void *p; 
p = malloc(100);
if (p) 
{ 
  perror("malloc"); 
  return false;
}

但有人想,为什么要保证获得记忆呢?

#define GET_MEM(p,s,i) do{for(p=NULL,i=0;!(p=calloc(1,s))&&i<5;perror("calloc"),i++)}while(0)

此类决定的proscons是什么?应该怎么做?

2 个答案:

答案 0 :(得分:2)

  

为什么要保证获得记忆呢?

你的假设是错误的。

malloc() calloc()realloc()可能会失败。因此,当您请求的内存未成功分配时,这些函数将返回NULL。如果没有这个检查,那么你继续写入这个未分配的内存位置,导致未定义的行为。

如果你的问题是为什么在宏中有一个while循环。以下链接解释得非常好

do { ... } while (0) — what is it good for?

答案 1 :(得分:1)

首先,这是不正确的,实际上与它应该做的相反:

void *p; 
p = malloc(100);
if (p) 
{ 
  perror("malloc"); 
  return false;
}

此if语句说:if( malloc succeeded ){ return AN_ERROR; }

应该说:

void *p; 
p = malloc(100);
if( NULL == p ) 
{ 
  perror("malloc"); 
  return false;
}

至于你的问题:

  

但有人想,为什么要保证获得记忆呢?

正如Gopi所说,你不能保证获得记忆。你很可能会耗尽内存,因此无法分配。您不太可能耗尽所有可用内存用于该过程,但可能会发生。这就是检查像malloc()calloc()realloc()这样的函数返回的原因。

如果没有足够的内存且您必须准备好处理它,那么任何这些内存分配函数都可能失败。让我们假设您为字符串分配空间,但malloc失败,您不检查:

int main(int argc, char *argv[]){
    char stringToCopy[] = "Some very long string would be here ...";
    char *stringBuffer = malloc( 1000 ); // 1000 char buffer
    // Malloc failed and we did not check for it
    strncpy(stringBuffer, stringToCopy); /* UNDEFINED BEHAVIOUR */
    return 0;
}

所以在这种情况下,malloc失败了,我们继续尝试将字符串复制到缓冲区。一旦我们开始这样做,我们就会导致未定义的行为。通常,这种操作会导致程序因Segmentation Fault而崩溃。

这可能很严重,可能导致数据丢失或服务丢失。至少,分段错误会给用户带来不便。

作为一些一般规则:始终检查malloc()calloc()realloc()的返回值; 从不盲目相信这些功能是成功的。

您是否选择在宏内部进行此检查是您自己的选择(没有许多优点/缺点),但只需确保执行检查并正确执行。