caddy-caddy
caddy-caddy

Reputation: 205

Releasing memory of structure fields in an array in C

I'm writing a function in C which adds a new product entry to an array of structs. The array is defined in the following structure:

struct product_array {
    struct product *arr;
    unsigned int count; //Initially set to NULL, counts the number of entries
    };

The array is dynamically allocated, but each time a new entry is added it should be reallocated. Each element of an array consists of product structure:

struct product {
    char *title;  
    char code[8]; // Should be truncated to 7 characters
   };

This is what I wrote:

 void add_product(struct product_array *pa, const char *title, const char *code)


    {
        pa->arr = realloc(pa->arr, sizeof(struct product) * (pa->count + 1));
        if (pa->arr == NULL)
            return NULL;

        char *temp = malloc(strlen(title) + 1); // for title memory 
//should be dynamically allocated separately
        if (temp == NULL){
            return NULL;
        }

        memmove(temp, title, (strlen(title) + 1));
            title = temp;


        pa->arr[pa->count].title = title;

        int j = 0;
            while (*code) {
                pa->arr[pa->count].code[j] = (*code);
                code++;
                j++;
                if (j == 7)
                    break;
            }
        pa->arr[pa->count].code[j] = '\0';

        pa->count++;

     } 

It seems to work fine (though I'm not sure if I used realloc correctly). But now I'm supposed to release the memory. I did it by writing:

free(pa->arr);

It also seems to be okay. But now I'm supposed to release memory which was allocated for title. To do that I should change main.c.

int main()
{
    struct product_array pa;
    pa.count = 0;
    pa.arr = NULL;

    add_product(&pa, "Product 1", "1111");

    add_product(&pa, "Product 2", "123320");

    add_product(&pa, "Product 3", "565496845");

}

And here I'm lost.

free (pa.arr->title);

doesn't seem to work.

Would really appreciate your help.

Upvotes: 0

Views: 197

Answers (3)

ericzundel
ericzundel

Reputation: 550

In your main() class, you allocated 3 different instances of 'title', when you go to free the memory, you need to free 3 different instances of 'title'. The simple answer is to just loop through pa->arr and free the title from each member.

One trick I used when writing 'C' is to create a function that deallocates the members of a struct. Then if you are allocating in an array like above, you just loop through the array calling the free_() function to free all the members of the struct.

void free_product(struct product *p) {
  free (p->title);
  /* If you dynamically allocate more fields in p, free them here */
}

void free_product_array(struct product_array *pa)
{
  int i;
  for (i = 0 ; i < pa->count; i++) {
    free_product(&pa->arr[i]);
  }
  free (pa->arr);
}

Your case is a bit different that what I normally do. I usually free the pointer itself at the end of the function, but I wouldn't do that here because you allocated an entire array for your product entries at once.

Upvotes: 0

gbuzogany
gbuzogany

Reputation: 1929

There are many problems there.

Be careful when using realloc: If you call realloc() and there is not enough room to enlarge the memory allocation pointed out it will copy everything to a new position, what may be slow. So, if the array is something that you expect to change it's size a lot, and you are not working in a platform that has tight memory size restrictions, you should do it in a different way. For example: allocate a space for 500 entries, and when it gets full, call a realloc to grow it to 1000 entries. This way you save some processing power (and memory bandwidth) by using more memory.

Also, make sure you understand how memory allocation works. A good reference is http://www-bcf.usc.edu/~dkempe/CS104/08-29.pdf

For example, if you call:

free(pa->arr);

Just the array will be freed, all the titles will be still allocated in memory, but you lost all the references to them. This is called memory leak (http://en.wikipedia.org/wiki/Memory_leak).

Upvotes: 0

michaelb
michaelb

Reputation: 451

Before freeing the pa->arr, you have to iterate over the array, freeing each structure's title separately, like this:

   for (int i = 0; i < pa.count; ++i)
   {
      free(pa.arr[i].title);
   }
   free(pa.arr);

Upvotes: 1

Related Questions