[英]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.