The usual approach here is that memory allocation functions are storing metadata about allocated space before actual memory chunk.
In that way, free()
just can read memory in front of the actual allocated block and it can find out how much memory should it actually deallocate.