处理malloc错误的巧妙方法,而不检查每次malloc调用后是否返回NULL?

在我的代码中,几乎每个函数都有一个或多个malloc调用,每次我必须执行以下操作:

char *ptr = (char *)malloc(sizeof(char) * some_int); if (ptr == NULL) { fprintf(stderr, "failed to allocate memory.\n"); return -1; } 

这是额外的四行代码,如果我在使用malloc后每次都添加它们,我的代码长度会增加很多..所以有一种优雅的方法来处理这个问题吗?

非常感谢!!

对不起,但在C中没有什么可以做的。除了…… 喘息…将它全部包装在宏中 ,这将自动执行if检查并允许您每次编写自定义error handling代码。 在那里,我说了。

说真的,C并不意味着提供这样的便利。 如果您不介意当场退出该程序,您可以将其包装在当然在分配失败时exit的function中 – 但这不是一般解决方案。

在消耗所有内存时,尝试偶然发现并不是很重要。 不妨称之为退出:

 char* allocCharBuffer(size_t numberOfChars) { char *ptr = (char *)malloc(sizeof(char) * numberOfChars); if (ptr == NULL) { fprintf(stderr, "failed to allocate memory.\n"); exit(-1); } return ptr; } 

你可以使用宏。 这比将此代码分组到函数中要便宜,因为宏没有函数调用所产生的开销。 宏通过编译的预处理器阶段进行扩展,可以通过gcc中的“-E”选项进行validation。 现在说我们有func1(),func2(),func3()

 #define MY_MALLOC(_ptr,_count, _lbl) \ do { \ if (NULL == (ptr = malloc(sizeof(char) * _count))) { \ fprintf(stderr, "Failed to allocate memory.\n"); \ goto _lbl; \ } \ } while(0) func1() { char *ptr; MY_MALLOC(ptr,10,Error); .... ... return (0); Error: return (1); } func2() { char *ptr; MY_MALLOC(ptr,10,Error); .... ... return (0); Error: return (1); } func3() { char *ptr; MY_MALLOC(ptr,10,Error); .... ... return (0); Error: return (1); } #undef MY_MALLOC 

当你没有真正的error handling(除了打印和退出)之外,简单而成熟的解决方案是定义一个包含检查的函数safe_malloc。 (编辑:或者,当然,还有一个宏。无论你的船是什么岩石。)

如果错误条件始终如此简单(打印错误消息并返回),则可以重写以保存行。

 int errmsg(const char *msg, int retval) { fprintf(stderr, "%s\n", msg); return retval; } 

 if ((ptr = malloc(size)) == NULL) return errmsg("failed to allocate memory.", -1); /* ... */ free(ptr); 

C运行时应该清理所有资源,包括打开文件,缓冲区和分配的数据。 即便如此,我喜欢使用int atexit( void(*)(void)) ,它会在正常退出时调用注册函数。 如果atexit返回非零值,也会立即退出,这意味着您的函数未注册。

 #include  void register_cleanup ( void ( *cleaner )( void )) { if ( atexit ( cleaner )) { fprintf ( stderr, "Error, unable to register cleanup: %s\n", strerror ( errno )) ; exit ( EXIT_FAILURE ) ; } } 

然后退出malloc失败。

 #include  void *malloc_or_die ( size_t size ) { void *dataOut = malloc ( size ) ; if ( !dataOut ) { fprintf ( stderr, "Error, malloc: %s\n", strerror ( errno )) ; exit ( EXIT_FAILURE ) ; } return dataOut ; } void main() { register_cleanup ( cleaner_fnc ) ; ... void *data = malloc_or_die ( 42 ) ; do_stuff ( data ) ; return 0 ; } 
 #define my_malloc_macro(size, ptr) do { \ ptr = malloc(size); \ if(!ptr) { \ printf("malloc failed\n"); \ return -1; \ } \ } while(0) 

或者你可以使用extern。

在main.c中定义一个函数:

  void sj_handleException(bool fatal, const char* msg, const char* libMsg){ fprintf(stderr, msg); if(libMsg != NULL) fprintf(stderr, libMsg); if(fatal) exit(EXIT_FAILURE); } 

mallocs内存添加的任何文件都与前向声明一样:

 extern void sj_handleException(bool fatal, const char* msg, const char* libMsg) 

现在将malloc写成:

 char *ptr = (char *)malloc(sizeof(char) * some_int); if (ptr == NULL) sj_handleException(true, "failed to allocate memory.\n", NULL); 

您的malloc内存的代码中的位置与处理exception的main.c之间的链接是由链接器在后台生成的; 即使两个源文件存在于不同的源文件中,它也会将调用映射到函数。