2010-02-28 22 views
5

mi función:en C: ¿Por qué existe una estructura asignada de pila fuera de la función?

struct hostent * gethost(char * hostname){ 
    if(/*some condition under which I want 
     to change the mode of my program to not take a host*/){ 
     return null 
    } 
    else{ 
     struct hostent * host = gethostbyname(hostname); 
     return host; 
    } 
} 

en el principal:

struct hostent * host = gethost(argv[2]); 

(ignore los errores menores en el código, estoy vomitando de la memoria)

Esto funciona bien. y Valgrind no me dice que estoy perdiendo la memoria, a pesar de que no estoy liberando.

¿Por qué? Pensé que las cosas asignadas en la pila desaparecen con la llamada a la función de regresar? o es porque devuelvo el puntero? ¿Es esto peligroso de alguna manera?

Respuesta

10

host no está asignado en la pila, solo un puntero está en la pila. El puntero se copia cuando la función regresa, por lo que no hay nada de malo en el código.

Tenga en cuenta que gethostbyname en realidad no asigna dinámicamente la memoria. Siempre devuelve un puntero al mismo bloque de memoria estáticamente asignado, por lo que valgrind no informa una fuga. Tenga cuidado, sin embargo, porque eso significa que debe copiar el hostent devuelto por su función si desea guardar el valor para más adelante porque las llamadas posteriores al gethost lo sobreescribirán.

+0

Ah, muchas gracias. Entonces, ¿es exclusivo de 'gethostbyname'? si hiciera esto para un 'char *', por ejemplo, ¿los valores en esa matriz podrían sobrescribirse más tarde? Mi programa solo tiene que tratar con un host por ejecución, por lo que debería estar bien. –

+0

Si el valor señalado por un puntero se sobrescribe en llamadas posteriores depende de la función a la que llama. Para cualquier función de biblioteca estándar de C que devuelva un puntero que no pase, puede asumir que está devolviendo un puntero a la memoria estática y puede sobreescribirse. – Gabe

0

Bueno, la memoria no se pierde hasta que se pierden todas las referencias a ella, en su ejemplo, se devuelve el puntero, por lo que todavía hay una referencia.

Sin embargo, en mi opinión es una mala decisión de diseño en la mayoría de los casos confiar en otra parte del código para liberar memoria dinámica. Si la función necesita devolver una estructura, por ejemplo, la persona que llama debe hacerlo y pasar un puntero a la estructura.

+2

La memoria no se ha filtrado porque 'gethostbyname' no hace la asignación dinámica. Devuelve un puntero estático cada vez. – Gabe

+2

¿Y quién, ora, diga, rastrea referencias en este puntero?:) – vladr

+2

Nadie rastrea las referencias al puntero. El bloque de memoria se asigna cuando la biblioteca de socket se carga y no se desasigna hasta que el proceso finaliza o la biblioteca de socket se descarga. – Gabe

2

del manual:

RETURN VALUE 
     The gethostbyname() and gethostbyaddr() functions return the hostent 
     structure or a NULL pointer if an error occurs. On error, the h_errno 
     variable holds an error number. When non-NULL, the return value may 
     point at static data, ... 

Algunos memoria se reserva en el tiempo de compilación (es decir, dentro del binario del código.) Para la estructura, la función devuelve un puntero a esta memoria.

3

Está bien y se filtra porque el puntero devuelto no apunta a los datos en la pila o en el montón, sino en alguna variable estática.

http://linux.die.net/man/3/gethostbyname:

Las funciones gethostbyname() y gethostbyaddr() puede devolver punteros a los datos estáticos, que pueden ser sobrescritos por las llamadas posteriores. Copiar la estructura de almacenamiento no es suficiente, ya que contiene punteros; se requiere una copia profunda

+0

¿Por qué "global"? Global y estático no son lo mismo. – Ben

Cuestiones relacionadas