繁体   English   中英

使用用户定义的函数检查malloc是否成功是个坏主意吗?

[英]Is it a bad idea to check whether malloc was successful using a user-defined function?

在C中使用malloc时,总是被告知要检查是否返回了NULL值,以查看是否发生了任何错误。 尽管我绝对理解为什么这很重要,但是不断地键入“ if”语句以及我想要在其中输入的内容来检查是否为每个我使用malloc的实例成功分配了内存有些麻烦。 为了使事情更快,我做了如下的函数来检查它是否成功。

#define MAX 25
char MallocCheck(char* Check);
char *Option1, *Option2;
int main(){
    Option1 = (char *)malloc(sizeof(char) * MAX);
    MallocCheck(Option1);
    Option2 = (char *)malloc(sizeof(char) * MAX);
    MallocCheck(Option2);
    return 0;
}

char MallocCheck(char* Check){
    if(Check == NULL){
        puts("Memory Allocation Error");
        exit(1);
    }
}

但是,无论搜索多少,我都从未见过有人在做这样的事情,所以我认为这是错误的,否则我不应该这样做。

为此目的使用用户定义的函数是否错误?如果是,原因为何?

错误检查是一件好事

制作一个辅助函数的代码更快,更好的是一件好事

详细信息取决于编码目标和小组的编码标准。

OP的方法还不错。 我更喜欢用分配来处理错误。 stderr @EOF上的以下输出在分配0字节(这不是内存不足故障)时不会抱怨返回NULL

void *malloc_no_return_on_OOM(size_t size) {
  void *p = mallc(size);
  if (p == NULL && size > 0) {
    // Make messages informative
    fprintf(stderr, "malloc(%zu) failure\n", size);
    // or 
    perror("malloc() failure");
    exit(1);
  }
  return p;
}

高级:可以使用宏对包含调用者函数和线路的DEBUG版本进行编码。

这是@chux的答案和评论的附录。

如前所述,DRY代码通常是一件好事,在特定实现中, malloc错误通常以相同的方式处理。

确实,某些系统(尤其是Linux)提供了乐观的malloc实现,这意味着malloc始终返回有效的指针(从不NULL ),并且在第一次将数据写入返回的指针时使用信号报告错误...这会导致错误处理的代码比问题中的代码稍微复杂一些。

但是 ,将错误检查移至其他函数可能会导致性能下降,除非编译器/链接器发现了问题并优化了函数调用。

这是内联函数(在较新的编译器上)或宏的经典用例。

#include <signal.h>

void handle_no_memory(int sig) {
  if (sig == SIGSEGV) {
    perror("Couldn't allocate or access memory");
    /* maybe use longjmp to stay in the game...? Or not... */
    exit(SIGSEGV);
  }
}

/* Using a macro: */
#define IS_MEM_VALID(ptr)                                                      \
  if ((ptr) == NULL) {                                                         \
    handle_no_memory(SIGSEGV);                                                 \
  }
/* OR an inline function: */
static inline void *is_mem_valid(void *ptr) {
  if (ptr == NULL)
    handle_no_memory(SIGSEGV);
  return ptr;
}

int main(int argc, char const *argv[]) {
  /* consider setting a signal handler - `sigaction` is better, but I'm lazy. */
  signal(SIGSEGV, handle_no_memory);
  /* using the macro */
  void *data_macro = malloc(1024);
  IS_MEM_VALID(data_macro);
  /* using the inline function */
  void *data_inline = is_mem_valid(malloc(1024));
}

宏和内联函数都可以防止代码跳转和函数调用,因为if语句现在是函数的一部分,而不是外部函数。

使用inline ,编译器将获取汇编代码并将其放在函数中(而不是执行函数调用)。 为此,我们必须信任编译器,以使其正常工作(通常比我们做得更好)。

当使用宏时,预处理器负责处理事务,我们不需要信任编译器。

在这两种情况下,函数/宏都位于文件本地(请注意static关键字),从而允许编译器(而非链接器)执行任何优化。

祝好运。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM