Question

The prototype of gethostbyname_r is:

int gethostbyname_r(const char *name,
    struct hostent *ret, char *buf, size_t buflen,
    struct hostent **result, int *h_errnop);

To avoid the non-reentrant gethostbyname, I wrote up these stuff:

int host2addr(const char *host, struct in_addr *addr) {
    struct hostent he, *result;
    int herr, ret, bufsz = 512;
    char *buff = NULL;
    do {
        char *new_buff = (char *)realloc(buff, bufsz);
        if (new_buff == NULL) {
            free(buff);
            return ENOMEM;
        }   
        buff = new_buff;
        ret = gethostbyname_r(host, &he, buff, bufsz, &result, &herr);
        bufsz *= 2;
    } while (ret == ERANGE);

    if (ret == 0 && result != NULL) 
        *addr = *(struct in_addr *)he.h_addr;
    else if (result != &he) 
        ret = herr;
    free(buff);
    return ret;
}

This is pretty the same as the example in GNU document and also the implemention in eglibc-2.15 for gethostname.

But I noticed that, there are h_name, h_aliases, h_addr_list in a struct hostent:

struct hostent {
   char  *h_name;            /* official name of host */
   char **h_aliases;         /* alias list */
   int    h_addrtype;        /* host address type */
   int    h_length;          /* length of address */
   char **h_addr_list;       /* list of addresses */
}

Therefore I wonder if that really do not matter not to free the contents those pointers refer to. Is there some other mechanism handling those memories?

Was it helpful?

Solution

You should print out the values of the pointers in that struct to find out the answer to your question. You'll discover that they all point to data inside the buffer you allocated.

So a single free is all you need to free up all the memory.

But this also means that you must not free that allocation until you've finished using or copying whatever data you're interested in. You're freeing too early in your code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top