1

I'm allocating an array of of "Todo" structs on the heap like so:

struct Todo *todos = malloc(n * sizeof(*todos));

My understanding is that I have now allocated memory for all of my n Todo structs. So if I want to save some values I can just do for example:

todos[i].id = 1;

The problem now is that if I try to free that memory using free(&todos[i]); I get an error telling me that I haven't allocated that pointer.

My question is now, do I just need to free the todos array and not every element on its own?

user2403221
  • 435
  • 1
  • 3
  • 12

3 Answers3

5

You have allocated one single block of memory for all your Todo structures. You can not free a single element. Just like you should not free elements of a non-heap allocated array.

Each call to malloc (or calloc) should be matched by a single call to free.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
2

A little bit of background to Some programmer dude's answer

C11 standard, 7.22.3.3 "The free function", paragraph 2:

The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.

[emphasis by me]

Background (second level...) is that typically, you did not only receive the memory starting at the pointer, but additionally there is some kind of (machine/OS specific) control block right before the pointer's address that is needed to free the memory again.

You might try to peek at this control block by reading some bytes right before the pointer (just out of curiosity), but be aware that this actually is undefined behaviour as well (so don't ever do this in production code!) and might lead to your programme crashing.

Aconcagua
  • 24,880
  • 4
  • 34
  • 59
0

As a reference, always that you do:

WhateverTypeInTheWorld *var1 = malloc(whateveryouwanttocompletearray);

then, you have to do

free(var1);  /* use the same value you received from malloc() */

to return the memory back... as you did only one malloc(), you can do only one free() and pass to it the same pointer you got from malloc().

When you write:

free(&todos[i].i);

you are passing free the i-esim element field i's address, and not the pointer you received from malloc(). Probably you understood that you can free part of the memory you received... but it doesn't work that way... you get the memory in chunks, and you have to return it in those same chunks you received from malloc.

Luis Colorado
  • 10,974
  • 1
  • 16
  • 31