Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

malloc() question...

1 view
Skip to first unread message

Chad

unread,
Nov 16, 2010, 3:12:45 PM11/16/10
to
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?

Ian Collins

unread,
Nov 16, 2010, 3:22:03 PM11/16/10
to

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

--
Ian Collins

Chad

unread,
Nov 16, 2010, 3:24:33 PM11/16/10
to

I thought 20 was ot type int.

Ian Collins

unread,
Nov 16, 2010, 3:27:54 PM11/16/10
to

It is, but the parameter for malloc is size_t and the unit of the value
requested is bytes.

--
Ian Collins

Seebs

unread,
Nov 16, 2010, 3:52:39 PM11/16/10
to

> char *a = malloc(20);

> and then do

> free(a);

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.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.

arnuld

unread,
Nov 16, 2010, 11:42:23 PM11/16/10
to
> On Tue, 16 Nov 2010 20:52:39 +0000, Seebs wrote:

>> On 2010-11-16, Chad <cda...@gmail.com> wrote:
>> 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?

> 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 ?

--
www.lispmachine.wordpress.com

James Waldby

unread,
Nov 17, 2010, 12:56:46 AM11/17/10
to

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

--
jiw

Seebs

unread,
Nov 17, 2010, 1:08:26 AM11/17/10
to
On 2010-11-17, arnuld <sun...@invalid.address> wrote:
>> On Tue, 16 Nov 2010 20:52:39 +0000, Seebs wrote:
>> 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.

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.

Keith Thompson

unread,
Nov 17, 2010, 2:38:03 AM11/17/10
to
Seebs <usenet...@seebs.net> writes:
[...]

> *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".

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Michael Foukarakis

unread,
Nov 17, 2010, 5:50:49 AM11/17/10
to

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).

William Hughes

unread,
Nov 17, 2010, 9:59:55 AM11/17/10
to
On Nov 17, 3:38 am, Keith Thompson <ks...@mib.org> wrote:

> Seebs <usenet-nos...@seebs.net> writes:
>
> [...]
>
> > *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

Keith Thompson

unread,
Nov 17, 2010, 11:44:29 AM11/17/10
to

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.

Seebs

unread,
Nov 17, 2010, 3:19:13 PM11/17/10
to
On 2010-11-17, Keith Thompson <ks...@mib.org> wrote:
> Seebs <usenet...@seebs.net> writes:
> [...]
>> *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?

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!

Keith Thompson

unread,
Nov 17, 2010, 3:47:29 PM11/17/10
to
Seebs <usenet...@seebs.net> writes:
> On 2010-11-17, Keith Thompson <ks...@mib.org> wrote:
>> Seebs <usenet...@seebs.net> writes:
>> [...]
>>> *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?
>
> 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.

Seebs

unread,
Nov 17, 2010, 4:59:58 PM11/17/10
to
On 2010-11-17, Keith Thompson <ks...@mib.org> wrote:
> 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.

Lew Pitcher

unread,
Nov 17, 2010, 5:26:23 PM11/17/10
to
On November 17, 2010 16:59, in comp.lang.c, usenet...@seebs.net wrote:

> On 2010-11-17, Keith Thompson <ks...@mib.org> wrote:
>> 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.

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?
--
Lew Pitcher
Master Codewright & JOAT-in-training | Registered Linux User #112576
Me: http://pitcher.digitalfreehold.ca/ | Just Linux: http://justlinux.ca/
---------- Slackware - Because I know what I'm doing. ------


Keith Thompson

unread,
Nov 17, 2010, 5:29:30 PM11/17/10
to
Seebs <usenet...@seebs.net> writes:
> On 2010-11-17, Keith Thompson <ks...@mib.org> wrote:
>> 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.

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

("In Soviet Russia ...")

Seebs

unread,
Nov 17, 2010, 5:41:01 PM11/17/10
to
On 2010-11-17, Keith Thompson <ks...@mib.org> wrote:
> They're not shoved into integers; integers are shoved into them.

Lew found the old K&R quote that probably got the integer stuff shoved
into my brain. :)

Bill Cunningham

unread,
Nov 19, 2010, 6:52:06 PM11/19/10
to

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


0 new messages