繁体   English   中英

测试ENOMEM的errno,而不是将一系列malloc调用与NULL进行比较

[英]Test errno for ENOMEM, instead of comparing a series of malloc calls to NULL

通常,一个测试malloc的结果不为NULL ,以确定内存分配是否成功。 通过一系列malloc调用,这将成为一个冗长或乏味的比较集。

相反,可以在malloc系列调用的顶部设置errno = 0 ,然后在最后测试errno == ENOMEM吗?
这假设如果任何分配失败,程序或功能将无法继续并且必须返回/纾困。 它还假设malloc调用是顺序的和连续的,并且根据手册, malloc只能将errnoENOMEM

一个例子是类似下面的代码:

#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的实现,就可以将errnoENOMEM 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.

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