[英]Test errno for ENOMEM, instead of comparing a series of malloc calls to NULL
通常,一个测试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;
}
(该示例使用main()
,但它也可能是另一个无法运行的函数,但程序可能会以其他方式继续运行,并且不会从程序中实际退出,并且free()
调用是必需的。)
我没有看到为什么这不能安全地完成的任何理由,但这不是我遇到的习语,因此问题。
不,你不能以便携的方式安全地做到这一点。
每7.5个错误<errno.h>
, C标准的第3段 :
初始线程中的
errno
值在程序启动时为零(其他线程中errno的初始值是一个不确定的值),但任何库函数都不会将其设置为零。 如果在本国际标准的功能描述中没有记录errno
的使用, 则可以通过库函数调用将errno
的值设置为非零值,无论是否存在错误。
由于没有记录malloc()
来按照C标准设置errno
,因此成功时可以自由地使用errno
。
相反,可以在malloc系列调用的顶部设置errno = 0,然后在最后测试errno == ENOMEM吗?
是的,只要记录了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
之后没有必要将errno
重置为零。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.