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

Cac*_*ito 0 c sockets linux getaddrinfo

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

#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);
[...]
Run Code Online (Sandbox Code Playgroud)

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

man getaddrinfo什么也没说errno;相反,它返回一个错误代码。为什么它可能在内部设置errnoEINVAL(22, Invalid argument)?

Rem*_*eau 8

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

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

所以,只要getaddrinfo() 本身不报告的错误代码,你比你根本无法依靠errno任何一种有意义的价值。 errno变化值只是一个副作用getaddrinfo()内部的实现您的系统上。

退出errno后唯一应该关注的时间getaddrinfo()getaddrinfo()返回时EAI_SYSTEM,只有那时才会errno对您产生有意义的价值。