C语言 “gethostbyname”如何返回“struct hostent *”而不要求调用方释放资源


struct hostent *gethostbyname(const char *name)

请注意,hostent.h_addr_list 是具有可变长度的字段。

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

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

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

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

过了一会儿:

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

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

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 结果引入伪代码表示形式。

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

注意线程安全。

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

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 的一部分,并且在旧平台上不可用。

最新更新