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!
--
Ian Collins
I thought 20 was ot type int.
It is, but the parameter for malloc is size_t and the unit of the value
requested is bytes.
--
Ian Collins
> 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.
>> 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 ?
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
> 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.
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"
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).
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
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.
>> 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!
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.
> 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.
> 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. ------
They're not shoved into integers; integers are shoved into them.
("In Soviet Russia ...")
Lew found the old K&R quote that probably got the integer stuff shoved
into my brain. :)
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