`gethostbyname`如何在不要求调用者释放资源的情况下返回`struct hostent *`?

时间:2012-07-18 15:03:11

标签: c network-programming

struct hostent *gethostbyname(const char *name)

请注意,hostent.h_addr_list是一个变量长度的字段。

函数gethostbyname如何具有返回指向结构的指针但不需要调用者释放资源的实现?

R. Stevens的着名书籍Unix Network Programming Vol 1中使用的所有示例都不包含释放这些返回指针的代码,我认为这些不是无知。 MSDN中的一个示例也做同样的事情example of usage

5 个答案:

答案 0 :(得分:5)

您链接的man页面包含答案:

  

当非NULL时,返回值可能指向静态数据,请参阅   以下注释。

过了一会儿:

  

函数gethostbyname()和gethostbyaddr()可能会返回指向静态数据的指针,   可能会被以后的电话覆盖。

答案 1 :(得分:3)

假设一个实现想要处理任意大的地址列表,它可以做这样的事情:

struct hostent *gethostbyname(const char *name) {
    static struct hostent *results = 0;
    static size_t resultsize = 0;
    size_t count = get_count_of_addresses(name)
    if (count > resultsize) {
        struct hostent *tmp = realloc(results, N * count + M);
        if (tmp) {
            results = tmp;
            resultsize = count;
        } else {
            // handle error, I can't remember what the docs say
        }
    }
    fill_in_hostent(results, name);
    return results;
};

可选地,套接字库可以在退出时执行某些操作以释放results(例如安装atexit处理程序),以避免调试报告内存泄漏的工具。

我忽略了地址数量可能会在规模结构和填充之间发生变化的可能性 - 实际上,您将获得DNS结果,然后对其进行处理,以便是不可能的。我把它留作两个单独的调用,以避免为DNS结果引入伪代码表示。

答案 2 :(得分:2)

可能指向静态内存。如果要保留多个结果,则需要对其进行深层复制。不是浅层副本,因为该结构本身包含指针。

小心线程安全。

答案 3 :(得分:1)

它可能指向静态内存,即每个调用都是相同的指针。

答案 4 :(得分:0)

MS告诉我们https://msdn.microsoft.com/en-us/library/windows/desktop/ms738524%28v=vs.85%29.aspx

The memory for the hostent structure returned by the 
gethostbyname function is allocated internally by the 
Winsock DLL from thread local storage. Only a single 
hostent structure is allocated and used, no matter how 
many times the gethostbyaddr or gethostbyname functions 
are called on the thread

所以它在Windows上是线程安全的,但是......

它已经从POSIX中删除了,man7.org告诉我们在Linux上,主机名语言环境不是线程安全的。 http://man7.org/linux/man-pages/man3/gethostbyname.3.html

..和MS告诉我们

The gethostbyname function has been deprecated 
by the introduction of the getaddrinfo function

不幸的是,替换(getaddrinfo,大多数平台上的线程安全)不是套接字1.x的一部分,并且在旧平台上不可用。