Search code examples
csocketsgetaddrinfo

Memory management with `addrinfo` structures


I've just started to work with UDP sockets in C and I have a question relating to memory management. Often examples show something of the following

struct addrinfo *result;    //to store results
struct addrinfo hints;      //to indicate information we want
:
:
:
if( (s = getaddrinfo(hostname, NULL, &hints, &result)) != 0){
  fprintf(stderr, "getaddrinfo: %s\n",gai_strerror(s));
  exit(1);
}
:
:
:
//free the addrinfo struct
freeaddrinfo(result);

I've also seen the introduction of an additonal local addrinfo structure used in a for loop to cycle through the result for the sake of extracting a particular entry...something like this

struct addrinfo *entry;    //to store a result from linked list
:
:
:
for (entry = result; entry != NULL; entry = entry->ai_next)
{
:
:
:
}

My question is why is result the only structure that gets passed to freeaddrinfo and not hints or entry? In other words, I've never seen anyone call freeaddrinfo(hints).

One other thing, should I be preallocating memory for or initializing structures of the form addrinfo? If so, how do I do that?


Solution

    1. Just skimmed through...it's because getaddrinfo dynamically allocates the memory?

    Yes. More specifically, it allocates memory for the linkedlist pointed to by result pointer. Since the library is allocating memory on your behalf, library implementors have also providing you with an API to free the memory.

    1. If that's the case, should I be pre-allocating memory / initializing entry in the example above? Why doesn't that get passed to freeaddrinfo

    No. entry is just a variable used to iterate through the list. It is very much similar to

    `for (i = 0; i < n; i++)` 
    

    loop you will find anywhere else. i is just an iterator.

    You don't have to use entry variable at all if you don't want to. You can iterate through the linkedlist with just a while loop

    while (result != NULL) {
        //Do what you have to do here
    
        result = result->ai_next;
    }
    

    If you observe closely, you will see that you are moving the result variable itself to the end of the list. If you iterate this way, there is no way for you to free the memory since you have lost the starting address which was returned to you by getaddrinfo(). To get around this, you can save the starting address in a temp variable and then use the while loop. Just add this line before the while loop.

    struct addrinfo *entry = result; //save the starting address
    while (...) {
    
    }
    

    You can call free on entry pointer now, instead of result. The effect would be the same.

    freeaddrinfo(entry);