2012-07-18 10 views
9
struct hostent *gethostbyname(const char *name) 

Tenga en cuenta que hostent.h_addr_list es un campo de longitud variante.¿Cómo `` gethostbyname` volver hostent struct * `sin requerir la persona que llama para liberar el recurso?

¿Cómo tiene la función gethostbyname la implementación que devuelve un apuntador que apunta a una estructura pero que no requiere que la persona que llama libere el recurso?

Todos los ejemplos utilizados en el famoso libro de Unix Red Programación Vol 1 por R. Stevens no contienen código para liberar los punteros devueltos y supongo que estos no son la ignorancia. También un ejemplo de MSDN hace lo mismo example of usage

+4

Esta es una de las razones por las que debe cambiar a 'getaddrinfo', que es la versión moderna de' gethostbyname'. Después de llamar a 'getaddrinfo', tienes que 'freeaddrinfo'. –

+0

Me gusta 'strerror'! – curiousguy

Respuesta

3

Suponiendo que una aplicación quiere manejar arbitrariamente grandes listas de direcciones, podría hacer algo como esto:

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; 
}; 

Opcionalmente, la biblioteca de sockets podría hacer algo para liberar results en la salida (como instalar una atexit controlador), para evitar las herramientas de depuración que informan una pérdida de memoria.

He ignorado la posibilidad de que el recuento de direcciones pueda variar entre dimensionar la estructura y completarla; en la práctica, obtendría el resultado DNS y luego haría cosas con él, por lo que no sería posible. Lo dejé como dos llamadas separadas para evitar introducir una representación de pseudocódigo para el resultado del DNS.

1

Probablemente apunta a la memoria estática, es decir, es el mismo puntero para cada llamada.

3

La página man se vincula a tiene la respuesta:

Cuando no nulo, el valor de retorno puede apuntar a datos estáticos, ver las notas abajo.

Y un poco más tarde:

Las funciones gethostbyname() y gethostbyaddr() puede devolver punteros a los datos estáticos, que pueden ser sobrescritos por llamadas posteriores.

1

Es puede punto a la memoria estática. Tendrá que hacer una copia profunda de eso si quiere conservar resultados múltiples. No es una copia superficial, porque esa estructura contiene punteros.

Cuidado de hilo de seguridad.

+0

Como señalé en el OP, el campo de h_add_list en struct hostent tiene longitud de variante. Eso significa que a la estructura estática se le debe asignar suficiente espacio para contener posibles listas largas de IP. – q0987

+0

Probablemente sea cierto, pero tenga en cuenta que la documentación y mi respuesta dicen "puede" ser estática. Puede haber circunstancias en las que la estructura se crea dinámicamente para acomodar una longitud excepcional, pero usa memoria estática para casos típicos y el rendimiento. –

0

MS nos dice que 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 

por lo que sería seguro para subprocesos en Windows, pero ...

Es sido bajado de POSIX, y man7.org nos dice que en el nombre de host Linux la configuración regional no es segura para subprocesos. http://man7.org/linux/man-pages/man3/gethostbyname.3.html

..y MS nos dice que

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

Por desgracia, la sustitución (getaddrinfo, el hilo de seguridad en la mayoría de plataformas) no era parte de los zócalos 1.x, y no está disponible en las plataformas de edad.

Cuestiones relacionadas