测试ENOMEM的errno,而不是将一系列malloc调用与NULL进行比较
通常,测试测试ENOMEM的errno,而不是将一系列malloc调用与NULL进行比较,c,C,通常,测试malloc的结果是否为NULL,以了解内存分配是否成功。通过一系列malloc调用,这将成为一组冗长或乏味的比较 相反,是否可以在malloc调用系列的顶部设置errno=0,然后在末尾测试errno==ENOMEM 这假设如果任何分配失败,程序或功能无法继续,必须返回/退出。它还假设malloc调用是连续的,并且根据手册,malloc只能将errno设置为ENOMEM 一个示例类似于以下代码: #include <stdlib.h> #include <errno
malloc
的结果是否为NULL
,以了解内存分配是否成功。通过一系列malloc
调用,这将成为一组冗长或乏味的比较
相反,是否可以在malloc
调用系列的顶部设置errno=0
,然后在末尾测试errno==ENOMEM
这假设如果任何分配失败,程序或功能无法继续,必须返回/退出。它还假设malloc
调用是连续的,并且根据手册,malloc
只能将errno
设置为ENOMEM
一个示例类似于以下代码:
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#define N (1 << 20)
int main()
{
double *a = NULL;
double *b = NULL;
double *c = NULL;
errno = 0;
a = malloc(N * sizeof *a);
b = malloc(N * sizeof *b);
c = malloc(N * sizeof *c);
if (errno == ENOMEM) {
perror(NULL);
free(a);
free(b);
free(c);
return EXIT_FAILURE;
}
errno = 0;
/* Do interesting stuff */
free(a);
free(b);
free(c);
return EXIT_SUCCESS;
}
#包括
#包括
#包括
#定义N(1)
相反,可以在malloc调用系列的顶部设置errno=0,然后在末尾测试errno==enome吗
是的,只要将malloc
的实现记录为将errno
设置为ENOMEM
,您就可以。C11标准(§7.22.3.4)中的规范只提到返回的指针将为NULL
,而不是将设置errno
,因此您的代码在技术上是不可移植的
macOS、Windows和Linux中默认的malloc
实现设置了errno
,因此这是世界上大多数计算机的覆盖范围。但是,如果需要真正的可移植性,最后只需编写
if (a == NULL || b == NULL || c == NULL)
{
// Handle the failure
}
附录:在malloc
s之后,无需将errno
重置回零。不,您不能以便携方式安全地执行此操作
根据C标准:
程序启动时,初始线程中的errno
值为零(其他线程中的errno初始值为不确定值),但决不能由任何库函数设置为零。如果本国际标准中的函数说明中未记录使用errno
,则库函数调用可将errno
的值设置为非零
因为malloc()
没有被C标准记录为设置errno
,成功后可以自由咀嚼errno
。我对答案的最佳猜测是,这确实是安全的,或者malloc将errno设置为ENOMEM在malloc实现中不如malloc返回NULL那么标准。如果malloc成功,但在b和C中失败,不会免费(b)和免费(c)给出错误吗?我知道它不会给C++带来错误,但是我不确定C编译器。如果你的代码> Malc ErnOn/Cuth>错误(可能不是这样,它是依赖于平台的),则您的代码是安全的。@suvenpandey如果malloc
失败,它也将返回NULL
。使用NULL
参数调用free
在C中是安全的。@user3629249我可以自己回答最后一个问题,我意识到:检查fp==NULL
,然后检查errno
的值以查看实际错误是什么r是。为了完整起见,标准中是否有相关章节的链接,或者这是不可能的?@9769953@9769953我已经添加了章节号。互联网上没有现成的HTML版本的标准,除非交上一大笔现金。我有一份我得到的最新草稿的PDF,并且出于所有意图和目的都是id诱人。@AlexeyFrunze和JeremyP:谢谢添加/链接!