Em C: Por que uma estrutura alocada da pilha existe fora da função?
-
23-09-2019 - |
Pergunta
minha função:
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;
}
}
em Main:
struct hostent * host = gethost(argv[2]);
(ignore todos os erros menores no código, estou vomitando da memória)
Isso funciona bem. E Valgrind não me diz que estou perdendo memória, apesar do fato de não estar libertando.
Por quê? Eu pensei que as coisas alocadas na pilha desaparecem com a chamada de função retornando? Ou é porque eu devolvo o ponteiro? Isso é perigoso de alguma forma?
Solução
host
não é alocado na pilha, apenas um ponteiro para ela está na pilha. O ponteiro é copiado quando a função retorna, portanto não há nada de errado com o código.
Observe que gethostbyname
Na verdade, não aloca dinamicamente a memória. Ele sempre retorna um ponteiro para o mesmo bloco de memória alocado estaticamente, e é por isso que Valgrind não relata um vazamento. Tenha cuidado, porém, porque isso significa que você precisa copiar o hostent
devolvido por sua função, se você quiser salvar o valor para mais tarde, porque outras chamadas para gethost
irá substituí -lo.
Outras dicas
Está bem e vaza porque o ponteiro retornado não aponta para dados na pilha ou na pilha, mas em alguma variável estática.
http://linux.die.net/man/3/gethostbyname:
As funções gethostbyname () e gethostbyaddr () podem retornar Ponteiros para dados estáticos, que podem ser substituídos por chamadas posteriores. Copiar o hostente da estrutura não é suficiente, pois contém ponteiros; Uma cópia profunda é necessária.
Do 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, ...
Alguma memória é reservada no tempo de compilação (ou seja, dentro do binário do código) para a estrutura, a função retorna um ponteiro para essa memória.
Bem, a memória não vazou até que todas as referências a ela sejam perdidas, no seu exemplo, o ponteiro é retornado, para que ainda haja uma referência.
No entanto, o IMHO é uma decisão de design ruim na maioria dos casos para confiar em outra parte do código para liberar memória dinâmica. Se a função precisar retornar uma estrutura, por exemplo, o chamador deve fazê -lo e passar um ponteiro para a estrutura.