0

From gethostbyname(3) - Linux manual

The functions gethostbyname() and gethostbyaddr() may return pointers
to static data, which may be overwritten by later calls.  Copying the
struct hostent does not suffice, since it contains pointers; a deep
copy is required.

I've written programs that make multiple calls to gethostbyname and haven't had anything break because of overwriting of static data.

Could I ask for an example when multiple calls to gethostbyname would overwrite this static data?

DeepDeadpool
  • 1,441
  • 12
  • 36
  • tldr for all answers; it's literally anytime you call it twice. – DeepDeadpool Apr 10 '18 at 17:08
  • 1
    of course, that's exactly what is stated in the manual, why surprised? – Jean-Baptiste Yunès Apr 10 '18 at 19:49
  • Because it says "may", not "will". My surprise comes that the answers outline that it happens every single time, and that I've been lucky to avoid hard to debug problems despite this. – DeepDeadpool Apr 11 '18 at 06:16
  • 1
    It cannot say "will" as it would impose too much constraint on the implementation. – Jean-Baptiste Yunès Apr 11 '18 at 07:12
  • or, phrased differently, it says "may" so that someone could write a *conforming* implementation that does *not* overwrite the buffer each call. afaict, this text is taken verbatim from the normative section of the POSIX specification, so it applies to all conforming implementations, not only the one on your system. – Andreas Grapentin Apr 11 '18 at 07:38

3 Answers3

2

It will be a problem when you do something like this:

struct hostent *google = gethostbyname("www.google.com");
struct hostent *youtube = gethostbyname("www.youtube.com");

printf("Official name of host for www.google.com: %s\n", google->h_name);
printf("Official name of host for www.youtube.com: %s\n", youtube->h_name);

printf("same? %s\n", google == youtube ? "yes" : "no");

The output will be

Official name of host for www.google.com: youtube-ui.l.google.com
Official name of host for www.youtube.com: youtube-ui.l.google.com
same? yes

which is wrong, as the official host name of www.google.com is www.google.com and not youtube-ui.l.google.com. The problem is that google and youtube point at the same location (as you can see from the same? yes output), so the information about www.google.com is lost when you execute gethostbyname again.

If you however do

struct hostent *google = gethostbyname("www.google.com");
printf("Official name of host for www.google.com: %s\n", google->h_name);

struct hostent *youtube = gethostbyname("www.youtube.com");
printf("Official name of host for www.youtube.com: %s\n", youtube->h_name);

then the output will be

Official name of host for www.google.com: www.google.com
Official name of host for www.youtube.com: youtube-ui.l.google.com

So as long as you process the hostent pointer of the first gethostbyname call before you do the second call, you will be fine.

Pablo
  • 13,271
  • 4
  • 39
  • 59
1
struct hostent *host1 = gethostbyname("host1");
struct hostent *host2 = gethostbyname("host2");

if(host1......)

the second call has overwritten (possibly) the result of the first one

pm100
  • 48,078
  • 23
  • 82
  • 145
  • Oh no! That's the most basic use case which I totally use in my programs. Almost. I end up creating the sockets before the next call though. – DeepDeadpool Apr 10 '18 at 17:05
1

Here's an example:

struct hostent *he1 = gethostbyname("host1");
struct in_addr *addr1 = (struct in_addr *)(he1->h_addr);

printf("addr1=%s\n", inet_ntoa(*addr1));    // prints IP1

struct hostent *he2 = gethostbyname("host2");
struct in_addr *addr2 = (struct in_addr *)(he2->h_addr);

printf("addr2=%s\n", inet_ntoa(*addr2));    // prints IP2

printf("addr1=%s\n", inet_ntoa(*addr1));    // prints IP1 (!)
dbush
  • 205,898
  • 23
  • 218
  • 273