How do free() know how many elements should be freed in a dynamic array?

L

lovecreatesbeauty

/*

How do free() know how many elements should be freed in a dynamic
array?

When free a single variable, the amount of byte of memory can be
retrieved from the type of variable itself.

Now, suppose there is an array of more than one element need to be
freed, as free() doesn't accept a argument indicating the size, how can
free() be aware of the count of elements? As shown in line #20.

Thank you

lovecreatesbeauty

*/

1 typedef struct
2 {
3 char account_name[200];
4 double balance;
5 } account;
6
7 int main(void)
8 {
9 int ret = 0;
10 const int ARR_CNT = 200;
11 account *pacc;
12 account *pacc_arr;
13
14 /* to allocate single object */
15 pacc = malloc(sizeof(*pacc));
16 free(pacc); /* size info. retrieved via type of variable
pacc */
17
18 /* to allocate object array */
19 pacc_arr = malloc(ARR_CNT * sizeof(*pacc));
20 free(pacc_arr); /* how can free() be aware of `ARR_CNT' */
21 return ret;
22 }
~
~
 
P

pemo

The std says nothing about how malloc etc work, but here's a common precise.

It's usually done by malloc(), calloc() et al [internally] keeping 'records'
of what's been allocated.

Say if you malloc() something of size 'x'. malloc() will allocate x bytes,
and keep a note of the memory allocated, via the address it returned to you
[usually in a node of a linked-list - address returned, size allocated].

For example, perhaps it will allocate x bytes out of a larger chunk of
memory it's previously allocated itself, and will 'remember' how big x is
for later, i.e., how big a part of the previoiusly allocated memory it
previouisly returned when you asked for it.

When you release memory, you pass the same address to free() that you got
back from malloc(). free() will typically reference the same internal
tables that malloc() has access to, to then determine how many bytes to free
up.
 
L

lovecreatesbeauty

Mike said:
You forgot to check the FAQ.
http://c-faq.com/

The answer to your (frequently asked) question is
in section 7

-Mike

Thank you, I just read the following section.

7.26 How does free know how many bytes to free?

Sorry, I made a mistake to remove my original post and post one updated
version again before read your reply, sorry.
 
G

Gordon Burditt

How do free() know how many elements should be freed in a dynamic

It just knows. Perhaps it's in a SQL database in a dungeon in
Microsoft's corporate headquarters. It's not your problem
HOW it knows.
When free a single variable, the amount of byte of memory can be
retrieved from the type of variable itself.

No, free() is not passed the type of the variable (except perhaps
by compiler magic).
Now, suppose there is an array of more than one element need to be
freed, as free() doesn't accept a argument indicating the size, how can
free() be aware of the count of elements? As shown in line #20.

It's up to it to know. It's not obligated to tell you.
Sometimes, the length or a pointer to the next byte after the
memory segment you allocated is found immediately *BEFORE* the
memory pointed at.

Gordon L. Burditt
 
L

Logan Shaw

Gordon said:
No, free() is not passed the type of the variable (except perhaps
by compiler magic).

I was thinking about that, but is there any standard that forbids
a C compiler from passing around dynamic type information with
pointers? It would certainly be atypical, but it seems like it
could be done.

- Logan
 
K

Keith Thompson

Logan Shaw said:
I was thinking about that, but is there any standard that forbids
a C compiler from passing around dynamic type information with
pointers? It would certainly be atypical, but it seems like it
could be done.

Sure, an implementation can decorate a pointer with any additional
information it likes, as long as it implements the semantics required
by the language.

For malloc() and free(), this would be difficult to do, since they
work with void* pointers. malloc()'s argument specifies only the size
in bytes, not the type.

Conceivably an implementation could perform some magic, so that

foo_t *ptr = malloc(sizeof *ptr);

would implicitly pass some additional type information into malloc().
But it would still have to deal with cases where no such information
is available:

void *ptr = malloc(42);
 
I

Ian

Logan said:
I was thinking about that, but is there any standard that forbids
a C compiler from passing around dynamic type information with
pointers? It would certainly be atypical, but it seems like it
could be done.
That would require the target platform's malloc and free to provide and
interpret this information, which is beyond the scope of the compiler,
it's a target implementation detail.

Ian
 
G

Gordon Burditt

When free a single variable, the amount of byte of memory can be
I was thinking about that, but is there any standard that forbids
a C compiler from passing around dynamic type information with
pointers? It would certainly be atypical, but it seems like it
could be done.

No, I don't think extra type information is forbidden, but I don't
think there is any way to ensure that it will *NEVER* be missing,
either. Casts to (void *) mustn't remove it, for example. And
what happens when pointer arithmetic is applied?

Gordon L. Burditt
 
I

Ian

Gordon said:
No, I don't think extra type information is forbidden, but I don't
think there is any way to ensure that it will *NEVER* be missing,
either. Casts to (void *) mustn't remove it, for example. And
what happens when pointer arithmetic is applied?
The same can be said for any dynamically allocated memory, the only
legal thing to pass to free is something obtained form malloc.

Casts don't change anything.

Ian
 
J

Jack Klein

That would require the target platform's malloc and free to provide and
interpret this information, which is beyond the scope of the compiler,
it's a target implementation detail.

Well, yes it is, but Logan's question is whether an implementation
would be allowed to do this, and of course the answer is yes, it
would.
 
J

Jack Klein

I was thinking about that, but is there any standard that forbids
a C compiler from passing around dynamic type information with
pointers? It would certainly be atypical, but it seems like it
could be done.

- Logan

There is nothing in the standard that forbids it, and in fact it would
make for an interesting debug implementation of the memory management
functions.

Imagine an implementation that kept a table of the addresses it
returned from malloc(), calloc(), and realloc(), and erased them when
they were freed. When a call was made to realloc() or free(), if
could search the table and if the passed pointer was not found,
generate an error message and terminate the program.
 
J

Jordan Abel

There is nothing in the standard that forbids it, and in fact it would
make for an interesting debug implementation of the memory management
functions.

Imagine an implementation that kept a table of the addresses it
returned from malloc(), calloc(), and realloc(), and erased them when
they were freed. When a call was made to realloc() or free(), if
could search the table and if the passed pointer was not found,
generate an error message and terminate the program.

Or generate a warning message and ignore.
 
J

Joe Wright

Jack said:
There is nothing in the standard that forbids it, and in fact it would
make for an interesting debug implementation of the memory management
functions.

Imagine an implementation that kept a table of the addresses it
returned from malloc(), calloc(), and realloc(), and erased them when
they were freed. When a call was made to realloc() or free(), if
could search the table and if the passed pointer was not found,
generate an error message and terminate the program.

I have done exactly that. I wrote a small 'library' I call Garbage
Eliminator (ge.c, ge.h) which traps the *alloc() calls and places their
results in a linked list. free() is also trapped and looks for its
argument in the list. If found, the list node is removed and the system
free() is called. If not found, it simply returns without comment.

I added a 'size_t size(void *p);' which will search my list for p and if
found return the argument to *alloc().

I also added 'void freeall(void);' which will free everything in the
list and then delete the list itself, and report for duty anew.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,226
Members
46,815
Latest member
treekmostly22

Latest Threads

Top