malloc() question...

C

Chad

Let's say I call malloc() like the following

char *a = malloc(20);

and then do

free(a);

Does 20 chars or 20 ints get freed?
 
I

Ian Collins

Let's say I call malloc() like the following

char *a = malloc(20);

and then do

free(a);

Does 20 chars or 20 ints get freed?

Why would 20 ints get freed when you have requested 20 chars? I guess
the answer would be "both" if sizeof(int) were 1!
 
A

arnuld

No.

The space that was allocated gets freed. It doesn't matter what you
think the pointer is; if it's the address malloc() returned, the whole
space is freed regardless.


We have not passed anything to the free() except pointer and it still free
()s the allocated memory. It means free() knows that char* a has 20x8
bits (assuming char is 8 bit here) without even telling it ?
 
J

James Waldby

We have not passed anything to the free() except pointer and it still
free ()s the allocated memory. It means free() knows that char* a has
20x8 bits (assuming char is 8 bit here) without even telling it ?

See <http://c-faq.com/malloc/freesize.html> for an answer to that
question, or see <http://c-faq.com/~scs/cgi-bin/faqcat.cgi?sec=malloc>
for more general info about malloc. If you want to find out how much
overhead an allocated block uses on your system, try a program like
the following (adjust the constants 21 and 28 if necessary).

/* Re: overhead bytes for allocated memory */
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int k;
char *now=NULL, *next;
for (k=21; k<28; ++k) {
next = malloc(k+1);
if (!next) exit(1);
if (now)
printf ("k=%2d next-now = %3ld now=%p\n",
k, next-now, now);
now=next;
}
return 0;
}

On my AMD x64 system this displayed the following, which
indicates that overhead is not less than 8 bytes (ie, 32-24).
k=22 next-now = 32 now=0x601010
k=23 next-now = 32 now=0x601030
k=24 next-now = 32 now=0x601050
k=25 next-now = 48 now=0x601070
k=26 next-now = 48 now=0x6010a0
k=27 next-now = 48 now=0x6010d0
 
S

Seebs

We have not passed anything to the free() except pointer and it still free
()s the allocated memory.
Yes.

It means free() knows that char* a has 20x8
bits (assuming char is 8 bit here) without even telling it ?

Stop thinking in terms of bits! BIT SIZE IS TOTALLY IRRELEVANT TO THIS
QUESTION. That you even mention bits says you are not understanding
something very fundamental about C:

*STORAGE IN C HAPPENS IN TERMS OF char NOT IN TERMS OF BITS*.

Bitfields are a semi-exception, but they are really packed into objects
of some integer type, and the integer type is still some number of chars
of storage.

Yes, free() knows how much space was allocated at that address. Part
of what malloc()/free() do is keep an internal table that allows free()
to free the space allocated. That's why you can only pass free()
pointers returned by malloc() (or null pointers).

When you request 20 bytes, malloc() records in some way how what block
of space it gave you (which may well have more than 20 bytes in it), so
that when you free the memory, that hunk of space can be made available
for further allocation.

-s
 
K

Keith Thompson

Seebs said:
*STORAGE IN C HAPPENS IN TERMS OF char NOT IN TERMS OF BITS*.

Bitfields are a semi-exception, but they are really packed into objects
of some integer type, and the integer type is still some number of chars
of storage.

You mean struct, not integer, yes?
Yes, free() knows how much space was allocated at that address. Part
of what malloc()/free() do is keep an internal table that allows free()
to free the space allocated. That's why you can only pass free()
pointers returned by malloc() (or null pointers).

It's conceivable that the memory allocation system doesn't even know
how much space was allocated, as long as it can arrange for free()
to do the right thing. A hypothetical example: You call malloc(10),
and it actually allocates 16 bytes, without remembering that you
asked for only 10. Or maybe it remembers both the 10 and the 16,
so it only has to copy 10 bytes if you call realloc(). Later, the 16
bytes following your allocation are free()d, and the system combines
them with the original 16 bytes to create a 32-byte allocated block
(perhaps because it guesses that you might want to call realloc() to
expand it further). Not necessarily plausible, but entirely legal.
When you request 20 bytes, malloc() records in some way how what block
of space it gave you (which may well have more than 20 bytes in it), so
that when you free the memory, that hunk of space can be made available
for further allocation.

Right. Note that the "table" you mentioned earlier needn't be any
particular data structure; information about allocated memory could be
scattered through the "heap".
 
M

Michael Foukarakis

Let's say I call malloc() like the following

char *a = malloc(20);

and then do

free(a);

Does 20 chars or 20 ints get freed?

It's impossible to say. It depends on the implementation, specifically
how much space is actually allocated by malloc() when you request 20
bytes (20 bytes + bookkeeping + header + footer etc).
 
W

William Hughes

[...]
*STORAGE IN C HAPPENS IN TERMS OF char NOT IN TERMS OF BITS*.
Bitfields are a semi-exception, but they are really packed into objects
of some integer type, and the integer type is still some number of chars
of storage.

You mean struct, not integer, yes?
Yes, free() knows how much space was allocated at that address.  Part
of what malloc()/free() do is keep an internal table that allows free()
to free the space allocated.  That's why you can only pass free()
pointers returned by malloc() (or null pointers).

It's conceivable that the memory allocation system doesn't even know
how much space was allocated, as long as it can arrange for free()
to do the right thing.  A hypothetical example: You call malloc(10),
and it actually allocates 16 bytes, without remembering that you
asked for only 10.  Or maybe it remembers both the 10 and the 16,
so it only has to copy 10 bytes if you call realloc().  Later, the 16
bytes following your allocation are free()d, and the system combines
them with the original 16 bytes to create a 32-byte allocated block
(perhaps because it guesses that you might want to call realloc() to
expand it further).  Not necessarily plausible, but entirely legal.


If you want plausible consider a system that preallocates a bunch
of small buffers for efficieny reasons. The size and number
of these buffers are set when the system is compiled.
Malloc has to know the size, but free does not. Free only
has to know if a points to one of these buffers. So it is quite
plausible that free(a) has no idea how much memory a points
to.


-William Hughes
 
K

Keith Thompson

Michael Foukarakis said:
It's impossible to say. It depends on the implementation, specifically
how much space is actually allocated by malloc() when you request 20
bytes (20 bytes + bookkeeping + header + footer etc).

Yes, but if it happens to free 20 ints (i.e., 20 * sizeof(int)
bytes), then that's purely coincidental.

In a followup, Chad said he thought it might free 20 ints because
20 is of type int. That's completely irrelevant. The argument
to malloc is converted to size_t (because that's the type of
malloc's parameter), and its value specifies the number of bytes
to be allocated.
 
S

Seebs

You mean struct, not integer, yes?

I'm pretty sure I mean integer (which has to be in a struct) -- maybe I'm
confused, but I thought I remembered that bitfield objects were combined
into integers which were secretly part of the structure in some way.
It's conceivable that the memory allocation system doesn't even know
how much space was allocated, as long as it can arrange for free()
to do the right thing. A hypothetical example: You call malloc(10),
and it actually allocates 16 bytes, without remembering that you
asked for only 10. Or maybe it remembers both the 10 and the 16,
so it only has to copy 10 bytes if you call realloc(). Later, the 16
bytes following your allocation are free()d, and the system combines
them with the original 16 bytes to create a 32-byte allocated block
(perhaps because it guesses that you might want to call realloc() to
expand it further). Not necessarily plausible, but entirely legal.

True. In practice, it nearly always has some idea of the size of the
block, because it handles more than one size of block. Though a naive
implementation built on mmap() could bypass that.
Right. Note that the "table" you mentioned earlier needn't be any
particular data structure; information about allocated memory could be
scattered through the "heap".

Yup!

-s
 
K

Keith Thompson

Seebs said:
I'm pretty sure I mean integer (which has to be in a struct) -- maybe I'm
confused, but I thought I remembered that bitfield objects were combined
into integers which were secretly part of the structure in some way.

Um, I don't think so, or at least I don't think the standard expresses
it in those terms.

6.7.2.1p10:

An implementation may allocate any addressable storage unit
large enough to hold a bitfield. If enough space remains,
a bit-field that immediately follows another bit-field in
a structure shall be packed into adjacent bits of the same
unit. If insufficient space remains, whether a bit-field that
does not fit is put into the next unit or overlaps adjacent
units is implementation-defined. The order of allocation of
bit-fields within a unit (high-order to low-order or low-order
to high-order) is implementation-defined. The alignment of the
addressable storage unit is unspecified.

It's not implied that these "addressable storage units" are integers.
 
S

Seebs

An implementation may allocate any addressable storage unit
large enough to hold a bitfield. If enough space remains,
a bit-field that immediately follows another bit-field in
a structure shall be packed into adjacent bits of the same
unit. If insufficient space remains, whether a bit-field that
does not fit is put into the next unit or overlaps adjacent
units is implementation-defined. The order of allocation of
bit-fields within a unit (high-order to low-order or low-order
to high-order) is implementation-defined. The alignment of the
addressable storage unit is unspecified.
It's not implied that these "addressable storage units" are integers.

Huh! Right you are. I guess this is cognitive overflow from the fact
that bitfields are declared with integer types. So I tend to think of
them as being shoved into integers.

-s
 
L

Lew Pitcher

Huh! Right you are. I guess this is cognitive overflow from the fact
that bitfields are declared with integer types. So I tend to think of
them as being shoved into integers.

FWIW, K&R C imposed (had?) an integer bias:

"A field may not overlap an int boundary; if the width would cause this to
happen, the field is aligned at the next int boundary.
...
Other restrictions to bear in mind: fields are unsigned; they may be
stored only in int's (or, equivalently, unsigned's); they are not arrays;
they do not have addresses, so the & operator cannot be applied to them."

The C Programming Language ((C) 1978, Bell Laboratories),
Section 6.7 - "Fields"

Perhaps that's what you remembered?
 
K

Keith Thompson

Seebs said:
Huh! Right you are. I guess this is cognitive overflow from the fact
that bitfields are declared with integer types. So I tend to think of
them as being shoved into integers.

They're not shoved into integers; integers are shoved into them.

("In Soviet Russia ...")
 
B

Bill Cunningham

Michael said:
It's impossible to say. It depends on the implementation, specifically
how much space is actually allocated by malloc() when you request 20
bytes (20 bytes + bookkeeping + header + footer etc).

Humm. Interesting thread. Answers some of my questions. I have this I am
thinking about using for a tftp header.
char paddding="0"; for two padding bytes.
short opcode=/*1-5*/ depending on the situation.
char *filename=/*whatever*/
char *mode=/*string mode*/

I've considered sticking all this about in a struct. The RRQ and WRQ header
is such

opcode|filename|1 byte|mode|1 byte
2 bytes string pad string pad

Would malloc() be a more streamlined answer?

Bill
 

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

Similar Threads


Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top