getaddrinfo() returns 0(成功)但将 errno 设置为 EINVAL (22)

getaddrinfo() returns 0 (success) but sets errno to EINVAL (22)

我在使用以下代码时遇到问题:

#include <errno.h>
#include <stdlib.h>

#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>


[...]
    struct protoent *tcp;
    struct addrinfo hint = {0};
    struct addrinfo *addrs;
    int             status;

    tcp = getprotobyname("tcp");
    if (!tcp)
        return  -EINVAL;
    hint.ai_family      = AF_UNSPEC;
    hint.ai_socktype    = SOCK_STREAM;
    hint.ai_protocol    = tcp->p_proto;
// errno is 0
    status  = getaddrinfo("localhost", "30002", &hint, &addrs);
// errno is 22
    if (status)
        return  -labs(status);
[...]

问题是虽然它有效(我将它用于 TCP 通信,它确实有效),但它不一致:

man getaddrinfo 什么也没说 errno;相反,它 returns 一个错误代码。为什么它可能在内部将 errno 设置为 EINVAL(22,无效参数)?

为什么会发生并不重要。 errno 仅当您自己的代码中的函数调用失败时才对您有意义,并且该函数 设计 以使用 errno 向您报告错误。但在大多数情况下 getaddrinfo() 并非如此。

getaddrinfo() 可能(并且很可能)在内部使用其他函数来完成其工作,如果这些函数失败,那么 getaddrinfo() 将根据需要在内部静默处理它们。如果这些错误对 getaddrinfo() 的工作是致命的,那么它将退出并根据需要返回给您自己的错误代码。

因此,只要 getaddrinfo() 本身 没有向您报告错误代码,您就不能完全依赖 errno 任何种有意义的值。 errno 更改值只是 副作用 getaddrinfo() 在您的系统上的内部实现。

getaddrinfo() 退出后,您唯一应该查看 errno 的时间是 getaddrinfo() returns EAI_SYSTEM,然后才会 errno 对你有有意义的价值。