моя функция:
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;
}
}
в основном:
struct hostent * host = gethost(argv[2]);
(проигнорируйте любые незначительные ошибки в коде, я извергаю из памяти),
это хорошо работает. и Valgrind не говорит мне, что я теряю память, несмотря на факт, который я не освобождаю.
Почему? Я думал, что материал, выделенный на стеке, исчезает с возвратом вызова функции? или это, потому что я возвращаю указатель? действительно ли это опасно всегда?
хост
не выделяется в стеке, только указатель на него находится в стеке. Указатель копируется, когда функция возвращается, поэтому в коде все в порядке.
Обратите внимание, что gethostbyname
на самом деле не выделяет память динамически. Он всегда возвращает указатель на один и тот же статически выделенный блок памяти, поэтому valgrind не сообщает об утечке. Однако будьте осторожны, потому что это означает, что вам нужно скопировать hostent
, возвращаемый вашей функцией, если вы хотите сохранить значение на потом, потому что дальнейшие вызовы gethost
перезапишут его.
Что ж, утечка памяти не происходит до тех пор, пока все ссылки на нее не будут потеряны. В вашем примере возвращается указатель, поэтому ссылка на него все еще существует.
Однако, imho, в большинстве случаев полагаться на другую часть кода для освобождения динамической памяти - плохое дизайнерское решение. Если функция должна вернуть структуру, например, вызывающий должен сделать это и передать указатель на структуру.
Это нормально, и утечка происходит потому, что возвращаемый указатель указывает не на данные в стеке или куче, а на некоторую статическую переменную.
http://linux.die.net/man/3/gethostbyname:
Функции gethostbyname() и gethostbyaddr() могут возвращать указатели на статические данные, которые могут быть перезаписаны последующими вызовами. Копирования struct hostent недостаточно, поскольку она содержит указатели; требуется глубокое копирование.
из руководства :
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, ...
Некоторая память резервируется во время компиляции (т.е. внутри двоичного кода) для структуры, функция возвращает указатель на эту память.