By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,172 Members | 1,146 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,172 IT Pros & Developers. It's quick & easy.

Question about malloc, alignment, ...

P: n/a
I am allocating a block of memory using malloc.
I want to use it to store a "header" structure
followed by structs in my application. How to calculate
the alignment without making any assumption
about the most restrictive type on my machine?
Thanks.
Nov 13 '05 #1
Share this Question
Share on Google+
36 Replies


P: n/a
Bertrand Mollinier Toublet
<be***********************@enst-bretagne.fr> wrote in
<bi************@ID-168218.news.uni-berlin.de>:
Bhalchandra Thatte wrote:
I am allocating a block of memory using malloc.
I want to use it to store a "header" structure
followed by structs in my application. How to calculate
the alignment without making any assumption
about the most restrictive type on my machine?


There is no need to coerce malloc into giving you the "right" alignment.
It is supposed to allocate blocks of memory suitably aligned to fit any
type.


Hmm, maybe I'm totally wrong, but reading the OP's question
again and again I suspect that he wants to calculate the
offsets of his data-structures, in which case the 'sizeof'
operator comes to mind. Too sad that no code was provided
by the OP.
--
My opinions are not those of my ex-employer.
Nov 13 '05 #2

P: n/a
Bhalchandra Thatte wrote:
I am allocating a block of memory using malloc.
I want to use it to store a "header" structure
followed by structs in my application. How to calculate
the alignment without making any assumption
about the most restrictive type on my machine?


If you must do it this way, the least clumsy way I can think of that is
guaranteed to work is to make a union of the header and the record itself,
and allocate a bunch of those. This isn't particularly wasteful if the size
of the header and the size of the record are approximately the same. This
way, you don't need to calculate the alignment at all. Just treat
element[0] as your header, and all the other elements as records.

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 13 '05 #3

P: n/a
On 31 Aug 2003 08:13:10 -0700, bd******@hotmail.com (Bhalchandra
Thatte) wrote:
I am allocating a block of memory using malloc.
I want to use it to store a "header" structure
followed by structs in my application. How to calculate
the alignment without making any assumption
about the most restrictive type on my machine?
Thanks.

The value returned by malloc is guaranteed to be suitable for any
object, including the different types of struct you describe.

Using notation _t for struct types and _ptr pointers to struct, we
start from scratch and build up. Remember to add error checking after
each call to malloc.

For just the header,
header_ptr = malloc(sizeof *header_ptr);
will allocate a sufficient quantity of properly aligned memory to hold
one header structure.

For one header and one struct1,
header_ptr = malloc(sizeof *header_ptr + sizeof *struct1_ptr);
struct1_ptr = (struct1_t*)(header_ptr+1);
will allocate enough space for one header structure and one other
structure. But we have no idea if the value assigned to struct1_ptr
is properly aligned this structure.

One possible solution is
n = (sizeof *header_ptr)/(sizeof *struct1_ptr)+1;
header_ptr = malloc(sizeof *header_ptr +
2 * (sizeof *struct1_ptr));
struct1_ptr = (struct1_t*)header_ptr+n;
Both pointers are guaranteed to be aligned properly.

For an array of k struct1,
n = (sizeof *header_ptr)/(sizeof *struct1_ptr)+1;
header_ptr = malloc(sizeof *header_ptr +
(k+1)*sizeof *struct1_ptr);
struct1_ptr = (struct1_t*)header_ptr+n;
will allocate enough space and align both pointers.

For two different types of application structures,
n1 = (sizeof *header_ptr)/(sizeof *struct1_ptr)+1;
n2 = ((n1+1)*(sizeof *struct1_ptr))/(sizeof *struct2_ptr)+1;
header_ptr = malloc(sizeof *header_ptr +
2 * (sizeof *struct1_ptr) +
2 * (sizeof *struct2_ptr));
struct1_ptr = (struct1_t*)header_ptr + n1;
struct2_ptr = (struct2_t*)header_ptr + n2;

You can extrapolate for more variety and quantity of structures .

However, this appears to be a maintenance nightmare. You would be
much better off with separate allocations instead of trying to force
one block to hold disparate types. Something like
header_ptr = malloc(sizeof *header_ptr);
struct1_ptr = malloc(k1 * sizeof *struct1_ptr);
struct2_ptr = malloc(k2 * sizeof *struct2_ptr);
<<Remove the del for email>>
Nov 13 '05 #4

P: n/a
On Sun, 31 Aug 2003 15:13:10 UTC, bd******@hotmail.com (Bhalchandra
Thatte) wrote:
I am allocating a block of memory using malloc.
I want to use it to store a "header" structure
followed by structs in my application. How to calculate
the alignment without making any assumption
about the most restrictive type on my machine?
Thanks.


sizeof() gives you always the size of a type. So use sizeof(struct
header) + sizeof(struct xyz) * number_of_struct xyz
as parameter to malloc to get enough space to store one struct header
+ the number of struct xyz elements you have to store there.

sizeof gives always the same answer for an given type. That is it
thinks you means to build an array of that type - even when you needs
only one of that. Let the compiler think about alignments, YOU have no
need to think on it.

--
Tschau/Bye
Herbert

eComStation 1.1 Deutsch Beta ist verügbar
Nov 13 '05 #5

P: n/a

"The Real OS/2 Guy" <os****@dv-rosenau.de> wrote in message
If you must do it this way, the least clumsy way I can think of that is
guaranteed to work is to make a union of the header and the record > >
itself, and allocate a bunch of those. No. You can do it, yes, but what if you have a header followed by a
different number of structs?

/* reserve memory for an header and 100 struct x */
struct header *p = malloc(sizeof(struct header) + 100 * sizeof(struct
x));
/* calculate the base address for struct x (struct x [0]) */
struct x *px = (struct x *) (p + 1);
px[99].member1 = value; /* fill the meber named member1 of the 100.


The way you do it is this.

typedef struct
{
int foo;
int bar;
int N;
}HEADER;

typedef struct
{
char fname[32];
char sname[32];
float salary;
}RECORD;

typedef union
{
HEADER hdr;
RECORD rec;
}MYUNION;

MYUNION *records = malloc( (1 + Nrecords) * sizeof(MYUNION));

It is tempting to say

records = malloc(sizeof(HEADER) + Nrecords * sizeof(RECORD));

but there is no way of guaranteeing that the second set of structures will
be correctly aligned. You can almost guarantee it, by padding HEADER out to
the nearest size of a double, bu this isn't cast iron.

Nov 13 '05 #6

P: n/a
On Sun, 31 Aug 2003 19:42:01 +0000 (UTC), "The Real OS/2 Guy"
<os****@dv-rosenau.de> wrote:
On Sun, 31 Aug 2003 15:13:10 UTC, bd******@hotmail.com (Bhalchandra
Thatte) wrote:
I am allocating a block of memory using malloc.
I want to use it to store a "header" structure
followed by structs in my application. How to calculate
the alignment without making any assumption
about the most restrictive type on my machine?
Thanks.


sizeof() gives you always the size of a type. So use sizeof(struct
header) + sizeof(struct xyz) * number_of_struct xyz
as parameter to malloc to get enough space to store one struct header
+ the number of struct xyz elements you have to store there.

Not if sizeof (struct header) is not a multiple of the alignment
requirement for struct xyz.

Consider a system where int is aligned on a multiple of 4 and
struct header {char c;};
struct xyz {int i;};

sizeof (struct header) could be 1 (there is no need for any padding
after c). and sizeof (struct xyz) could be 4. struct xyz must be
aligned on a multiple of 4 to insure i is aligned.

The sum of the two sizeof values will allocate 5 bytes aligned on a
multiple of 4 which is not sufficient to hold a struct header followed
by a struct xyz.
<<Remove the del for email>>
Nov 13 '05 #7

P: n/a
The Real OS/2 Guy wrote:
On Sun, 31 Aug 2003 16:28:12 UTC, Richard Heathfield
<do******@address.co.uk.invalid> wrote:
Bhalchandra Thatte wrote:
> I am allocating a block of memory using malloc.
> I want to use it to store a "header" structure
> followed by structs in my application. How to calculate
> the alignment without making any assumption
> about the most restrictive type on my machine?


If you must do it this way, the least clumsy way I can think of that is
guaranteed to work is to make a union of the header and the record
itself, and allocate a bunch of those. This isn't particularly wasteful
if the size of the header and the size of the record are approximately
the same. This way, you don't need to calculate the alignment at all.
Just treat element[0] as your header, and all the other elements as
records.

No. You can do it, yes, but what if you have a header followed by a
different number of structs?


You haven't the faintest idea what I was actually suggesting, have you? Try
reading it again.

<snip>

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 13 '05 #8

P: n/a
Bhalchandra Thatte wrote:
Richard Heathfield <do******@address.co.uk.invalid> wrote in message
news:<bi**********@hercules.btinternet.com>...
Bhalchandra Thatte wrote:
> I am allocating a block of memory using malloc.
> I want to use it to store a "header" structure
> followed by structs in my application. How to calculate
> the alignment without making any assumption
> about the most restrictive type on my machine?
If you must do it this way, the least clumsy way I can think of that is
guaranteed to work is to make a union of the header and the record
itself, and allocate a bunch of those. This isn't particularly wasteful
if the size of the header and the size of the record are approximately
the same. This way, you don't need to calculate the alignment at all.
Just treat element[0] as your header, and all the other elements as
records.


This idea is interesting, since it is the simplest, and involves
no computation on my part. And the size of my header is in fact
smaller than other structs.


Since you only have one header, if it's smaller than the records themselves,
that's perfect. Wastage minimised.
Meanwhile I went to a book shop, and browsed through a book
(C interfaces or something like that by Hansen I think). He suggests

union Alignment {
int a;
long b;
float c;
double d;
void (*f)(void) fptr;
Huh? I think this is a bug. (They happen.)
void* e;
...
}
He then uses sizeof(Alignment) and sizeof(header)
to calculate the offset.
In "C Unleashed" I suggest

typedef union
{
long l; /* if C99, consider using intmax_t instead */
unsigned long lu;
double f;
long double lf;
void *vp;
void (*fp)(void);
} ALIGN;

but, as I say, if you adopt my suggestion you won't need this.
I am still not comfortable with it. What if one missed
something in the union? Is it sufficient to list all
basic types provided by the language?


No. For the alignment thing to be ***guaranteed*** to work on a general
basis, you must list every type used by the program, which includes all
user-defined types (which is why implementing a generalised leak detector
is much harder than it looks). It would be sufficient, in *your* case, to
include

struct header hdr;

and

struct record rcd;

into the alignment structure. But of course my solution doesn't require you
to include any of the other types (into your program, to solve your current
problem). A simple union of struct header and struct record is sufficient.

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 13 '05 #9

P: n/a
On Sun, 31 Aug 2003 22:05:30 UTC, "Malcolm"
<ma*****@55bank.freeserve.co.uk> wrote:
typedef struct
{
int foo;
int bar;
int N;
}HEADER;

typedef struct
{
char fname[32];
char sname[32];
float salary;
}RECORD;

typedef union
{
HEADER hdr;
RECORD rec;
}MYUNION;

MYUNION *records = malloc( (1 + Nrecords) * sizeof(MYUNION)); It is tempting to say

records = malloc(sizeof(HEADER) + Nrecords * sizeof(RECORD));

but there is no way of guaranteeing that the second set of structures will
be correctly aligned. You can almost guarantee it, by padding HEADER out to
the nearest size of a double, bu this isn't cast iron.


It IS guaranteed that (pointer to struct) (<pointer to struct> + n)
results always to an well aligned pointer to any struct.
typedef struct x X;
typedef struct y Y;
typedef struct z Z;

typedef struct {
int type;
char flags;
X *px;
Y *py;
Z *pz;
} HEADER;

HEADER *p = malloc(sizeof(HEADER) + sizeof(X) + sizeof(Y) * nY +
sizeof(Z))

gives enough space to hold all 3 structs (whereas one of them is an
array of structs.

sample A: work with pointer arithmetic
p->px = (X*) (p + 1); /* base to struct X */
p->py = (Y*) (px + 1); /* base to struct Y[ny] */
p->pz = (Z*) (py + nY); /* base to struct Z */

Works always. That is because you needs ponter arithmetic even when
you addresses members of an array of structs.

sample B: work with byte counts
p->px = (X*) (((char *) p) + sizeof(HEADER)); /* the same as above */
p->py = (Y*) (((char *) px) + sizeof(X));
p->pz = (Z*) (((char *) py) + sizeof(Y) * ny);

Sample A and B delivers exactly the same result. Sample A is simple
beacuse the compiler does the actions of sample B implicite.

malloced_size = ((char *) (p->pz+1)) - (char *) p;
or
malloced_size = ((char *) p->pz) + sizeof(Z) - (char *) p;

All pointer to all structs are identical. structs are always in the
right size to get the object behind it gets aligned right. When an
object is on an aligned address a pointer to it must be aligned well.

How odd the alignment requirement of a mashine ever been, malloc
returns a well aligned address. Adding to that address any size_t
returned from sizeof results in an aligned address of the type sizeof
was worked on. As any struct has the same alignment you can savely
cast a pointer to struct x to pointer to struct y. You can savely work
with pointers to char too because each struct's size is always rounded
up to have the next object on an aligned address.

In practice you can forget about alignment problems because the
compiler works on it for you.

This may not true when you uses implementation defined things, such as
#pragma align - but then you leave ANSI C and gets unportable.

--
Tschau/Bye
Herbert

eComStation 1.1 Deutsch Beta ist verügbar
Nov 13 '05 #10

P: n/a
In article <fe**************************@posting.google.com >,
bd******@hotmail.com (Bhalchandra Thatte) wrote:
Meanwhile I went to a book shop, and browsed through a book
(C interfaces or something like that by Hansen I think). He suggests

union Alignment {
int a;
long b;
float c;
double d;
void (*f)(void) fptr;
void* e;
...
}
He then uses sizeof(Alignment) and sizeof(header)
to calculate the offset.
I am still not comfortable with it. What if one missed
something in the union?
He missed pointer to short, int, long, long long and pointer to struct;
he missed long long as well. All the pointers that I mentioned could in
principle have different size and alignment requirements than void*.
Is it sufficient to list all
basic types provided by the language?


On one very common architecture where sizeof (double) == 8, it would be
quite reasonable that structs with two consecutive double members have
alignment requirement of 16. And I cannot see anything in the C Standard
that would prevent this from happening.
Nov 13 '05 #11

P: n/a
On Mon, 1 Sep 2003 03:31:23 UTC, Richard Heathfield
<do******@address.co.uk.invalid> wrote:
Malcolm wrote:
"The Real OS/2 Guy" <os****@dv-rosenau.de> wrote:


[Actually, /I/ wrote the first bit...]

RJH>> > If you must do it this way, the least clumsy way
RJH>> > I can think of that is guaranteed to work is to
RJH>> > make a union of the header and the record itself,
RJH>> > and allocate a bunch of those.

TROS2G>> No. You can do it, yes, but what if you have a
TROS2G>> header followed by a different number of structs?

<snip>

(Over to Malcolm for a bit...)
The way you do it is this.

typedef struct
{
int foo;
int bar;
int N;
}HEADER;

typedef struct
{
char fname[32];
char sname[32];
float salary;
}RECORD;

typedef union
{
HEADER hdr;
RECORD rec;
}MYUNION;

MYUNION *records = malloc( (1 + Nrecords) * sizeof(MYUNION));


Thank you, Malcolm. It appears that *you* actually took the time to read
what I'd written, for which I am grateful. Reading is a dying art, is it
not?


Now your union has the size of the biggest struct. When the big struct
is 4 K, your header 20 bytes and the smallest struct is 16 bytes then
you needs more than 400 KB instead 20 + 16 * 100 = 1620 bytes when you
needs header + smallest struct [100].

The idea is really bad.

Understund how pointer arithmetic works and your memory usage is
thifty. Always let the compiler think about alignment - it is its work
to do so. sizeof is designed to deliver the size of a struct always so
that adding it to a byte pointer the resulting address will be aligned
right for each other object when the base pointer is aligned for.
Adding a counter to a pointer inreses the pointer of sizeof type *
conter bytes implicity.

Pointers to structs are addresses aligned to be pointer of struct (any
struct).

See my other artikle for more details.

--
Tschau/Bye
Herbert

eComStation 1.1 Deutsch Beta ist verügbar
Nov 13 '05 #12

P: n/a
On Sun, 31 Aug 2003 23:05:20 UTC, Barry Schwarz <sc******@deloz.net>
wrote:
On Sun, 31 Aug 2003 19:42:01 +0000 (UTC), "The Real OS/2 Guy"
<os****@dv-rosenau.de> wrote:
On Sun, 31 Aug 2003 15:13:10 UTC, bd******@hotmail.com (Bhalchandra
Thatte) wrote:
I am allocating a block of memory using malloc.
I want to use it to store a "header" structure
followed by structs in my application. How to calculate
the alignment without making any assumption
about the most restrictive type on my machine?
Thanks.
sizeof() gives you always the size of a type. So use sizeof(struct
header) + sizeof(struct xyz) * number_of_struct xyz
as parameter to malloc to get enough space to store one struct header
+ the number of struct xyz elements you have to store there.

Not if sizeof (struct header) is not a multiple of the alignment
requirement for struct xyz.

Consider a system where int is aligned on a multiple of 4 and
struct header {char c;};
struct xyz {int i;};

sizeof (struct header) could be 1 (there is no need for any padding
after c). and sizeof (struct xyz) could be 4. struct xyz must be
aligned on a multiple of 4 to insure i is aligned.


No sizeof(struct header) would be 4 when the alignment requirement of
a struct is a multiple of 4. Don't work with implementation defined
extensions (e.g. #pragma align) in that case. ANCI C requires that
each member of an array is on an aligned address. struct header[100]
must be 400 bytes in size to have 100 structs of that type aligned
right.

sizeof(char) is always 1. sizeof(struct) is always (sizeof member
rounded up to alignment for any type) + (sizeof next member rounded up
to alignment for any type) + ......

So the single char in the struct has a number of padding bytes to get
the struct the right size to come to the next aligned address. Check
it with any ANSI C compiler you can get in your hands - or simply read
the standard carefully.
The sum of the two sizeof values will allocate 5 bytes aligned on a
multiple of 4 which is not sufficient to hold a struct header followed
by a struct xyz.


Wrong. a char is not a stuct, even as a struct may contain (only) a
char, so the size of struct and char differs.

Use sizeof to get the size of a struct. add the number of of structs
to a pointer, cast the pointer to another struct type - and you're
guaranteed that this new pointer is well aligned to point to an
aligned stuct of that type. The size of an struct doesn't matter. It
is portable, it is ANSI C.

The size of an struct can differ from implementation to implementation
because each implementation has its own alignment requirements and the
size of a struct is based on the align requirements of each of its
members (including the last one). A struct is calculated:

size in bytes of 1. menber + padding bytes to get an address able to
hold an aligned object of any type
+ size in bytes ...
+ ...

So the size of a struct ends up so that a pointer to an aligned object
increased with the size of a struct results in a pointer to an aligned
object of any type.

Define a char! define thereafter another char - the compiler will
create both on different addresses - and each address will differ in
sizeof(char) + required bytes to get the next address aligned to hold
each other other object. It is always the job of the compiler to
define objects on aligned addresses.

When you plays around with implementation defined things (such as
#pragma align) then you leaves ANSI C and you gets unportable. In ANSI
C you can always count on the compiler that pointer arithmetic works
right, so whenever you have to build a pointer you gets a well aligned
pointer when you works on a well aligned pointer.

Increasing a pointer with a number of elements of that type results
always in an well aligned pointer of that type. All structs have equal
alignment requirements to get the next struct.

--
Tschau/Bye
Herbert

eComStation 1.1 Deutsch Beta ist verügbar
Nov 13 '05 #13

P: n/a
On Sun, 31 Aug 2003 23:21:11 UTC, bd******@hotmail.com (Bhalchandra
Thatte) wrote:
This idea is interesting, since it is the simplest, and involves union Alignment {
int a;
long b;
float c;
double d;
void (*f)(void) fptr;
void* e;
...
}
He then uses sizeof(Alignment) and sizeof(header)
to calculate the offset.


No need for such thing. sizeof delivers allways the needed size to get
the next aligned address if adding to an aligned pointer.

- all structs have the same align requirement.
- adding the number of structs to a pointer of that struct type gives
always the address of the next aligned struct
- casting a pointer to struct to another struct type changes nothing
except the type of the struct.
whenever the pointer is aligned to point to an aligned struct of one
type
it can be casted to another struct type without loosing the
alignment.
- for malloc you have to add the sizeo of each struct, because you
needs a
number of bytes big enough to hold the structs
- for simple pointer arithmetic you can simple add the number of
structs
to the base address of the parent struct to get the address of the
next struct.
whenever the address points to an aligned struct the resulting
address
does the same.
- you can cast a pointer to one struct to another struct. This tells
the
compiler only that the type and order of the members of that struct
are other than the one of the old struct. Whenever the address
points
an aligned struct it will do so thereafter too.

Simply forget about alignment. It is the job of the compiler to think
on it.
Based on this you can get different results from sizeof on different
implementations!
So when you have to serialise your memory you have to handle each
struct member separately when you have to work with different
implementation on them. But then you may have the problem of byte
order too.

--
Tschau/Bye
Herbert

eComStation 1.1 Deutsch Beta ist verügbar
Nov 13 '05 #14

P: n/a
In article <wmzsGguTDN6N-pn2-8RBo56s7xXBY@moon>,
"The Real OS/2 Guy" <os****@dv-rosenau.de> wrote:
On Sun, 31 Aug 2003 23:05:20 UTC, Barry Schwarz <sc******@deloz.net>
wrote:
Consider a system where int is aligned on a multiple of 4 and
struct header {char c;};
struct xyz {int i;};

sizeof (struct header) could be 1 (there is no need for any padding
after c). and sizeof (struct xyz) could be 4. struct xyz must be
aligned on a multiple of 4 to insure i is aligned.


No sizeof(struct header) would be 4 when the alignment requirement of
a struct is a multiple of 4. Don't work with implementation defined
extensions (e.g. #pragma align) in that case. ANCI C requires that
each member of an array is on an aligned address. struct header[100]
must be 400 bytes in size to have 100 structs of that type aligned
right.


There is no reason whatsoever why "struct header" should have a size
greater than one. It may on the compiler that you are using, in general
there is no reason for that assumption. It is absolutely possible that
struct header has an alignment requirement of 1, a size of 1, and an
array of 100 struct header has a size of 100, and everything works fine.
Nov 13 '05 #15

P: n/a
Bhalchandra Thatte wrote:

I am allocating a block of memory using malloc.
I want to use it to store a "header" structure
followed by structs in my application. How to calculate
the alignment without making any assumption
about the most restrictive type on my machine?


The memory returned by malloc is suitably aligned for
the most restrictive type on your machine.
Why not use that information ?

--
pete
Nov 13 '05 #16

P: n/a
On Mon, 1 Sep 2003, pete wrote:
What can a cpu do with a struct that has two double members,
when the the alignment requirements are for the size of the structure,
that a cpu can't can't do
when the structure alignment requirements are for the size of a member ?


perform operations for both members with a single instruction:

foo.a+=bar->a; foo.b+=bar->b; /* addpd xmm0, [eax]. requires bar->a to be
16 byte aligned. */

Nov 13 '05 #17

P: n/a
On Mon, 1 Sep 2003 07:41:29 +0000 (UTC), "The Real OS/2 Guy"
<os****@dv-rosenau.de> wrote in comp.lang.c:
On Mon, 1 Sep 2003 03:31:23 UTC, Richard Heathfield
<do******@address.co.uk.invalid> wrote:
Malcolm wrote:
"The Real OS/2 Guy" <os****@dv-rosenau.de> wrote:
[Actually, /I/ wrote the first bit...]

RJH>> > If you must do it this way, the least clumsy way
RJH>> > I can think of that is guaranteed to work is to
RJH>> > make a union of the header and the record itself,
RJH>> > and allocate a bunch of those.

TROS2G>> No. You can do it, yes, but what if you have a
TROS2G>> header followed by a different number of structs?

<snip>

(Over to Malcolm for a bit...)
The way you do it is this.

typedef struct
{
int foo;
int bar;
int N;
}HEADER;

typedef struct
{
char fname[32];
char sname[32];
float salary;
}RECORD;

typedef union
{
HEADER hdr;
RECORD rec;
}MYUNION;

MYUNION *records = malloc( (1 + Nrecords) * sizeof(MYUNION));


Thank you, Malcolm. It appears that *you* actually took the time to read
what I'd written, for which I am grateful. Reading is a dying art, is it
not?


Now your union has the size of the biggest struct. When the big struct
is 4 K, your header 20 bytes and the smallest struct is 16 bytes then
you needs more than 400 KB instead 20 + 16 * 100 = 1620 bytes when you
needs header + smallest struct [100].

The idea is really bad.


Maybe, maybe not.
Understund how pointer arithmetic works and your memory usage is
thifty. Always let the compiler think about alignment - it is its work
to do so. sizeof is designed to deliver the size of a struct always so
that adding it to a byte pointer the resulting address will be aligned
right for each other object when the base pointer is aligned for.
Adding a counter to a pointer inreses the pointer of sizeof type *
conter bytes implicity.

Pointers to structs are addresses aligned to be pointer of struct (any
struct).
Can you provide a reference from the C standard to support your
statement above? Frankly I know that you can't. It is completely
long. All pointers to structures have the same size and bitwise
representation. That is NOT the same as saying that all structures
have the same memory alignment.

Consider:

================
#include <stdlib.h>

struct one { char ch; };
struct two { long l; };

char *fred = malloc(sizeof(one) + sizeof(two));

struct two *ptr2 = fred + sizeof(one);

long x = ptr2->l;
================

Code equivalent to the above will generate an alignment fault on some
architectures.
See my other artikle for more details.


See ANSI/ISO/IEC 9899:1999 for accurate information.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
Nov 13 '05 #18

P: n/a
In article <wmzsGguTDN6N-pn2-CNxGTLudkZEV@moon>
The Real OS/2 Guy <os****@dv-rosenau.de> writes:
It IS guaranteed that (pointer to struct) (<pointer to struct> + n)
results always to an well aligned pointer to any struct.
This claim is unsupportable.
typedef struct x X;
typedef struct y Y;
typedef struct z Z;

typedef struct {
int type;
char flags;
X *px;
Y *py;
Z *pz;
} HEADER;

HEADER *p = malloc(sizeof(HEADER) + sizeof(X) + sizeof(Y) * nY +
sizeof(Z))

gives enough space to hold all 3 structs (whereas one of them is an
array of structs.
Example where it fails on (e.g.) SPARC (V6 through V9 inclusive):

struct x { char elem; };
struct y { int elem; };
struct z { double elem; };

Here sizeof(X) is 1, and sizeof(HEADER) is either 20 (32-bit mode)
or 32 (64-bit mode). Y and Z have sizes 4 and 8 respectively, and
require 4 and either 4 or 8 (depending on compiler and flags) byte
alignments, so we get:

#define H 20 /* or 32 */
p = malloc(H + 1 + 4 * nY + 8)

(which is definitely an odd number, because of the "+1" in the middle,
not that this matters too much). Then:
sample A: work with pointer arithmetic
p->px = (X*) (p + 1); /* base to struct X */
(assuming p!=NULL of course) this is OK, but:
p->py = (Y*) (px + 1); /* base to struct Y[ny] */


if p is something like 0x4041a800, (p+1) is (unsigned long)p + H
(where H is either 20, hex 0x14, or 32, hex 0x20). (Recall that
I have specified SPARC V6-through-V9; pre-V9 all pointers are 32
bits, and in V9 one usually runs in 32-bit mode, with an "ILP32"
model, or in 64-bit mode, with an "I32LP64" model, so that pointers
fit in "long"s in either case.)

In 32-bit mode, then, p+1 produces address 0x4041a814, which is
valid for "X *px", but (px+1) produces address 0x4041a815, which
is *not* valid for "Y *py". In particular, "int"s must be aligned
on four-byte boundaries.

It *is* possible to make this kind of allocation work, using any
of various tricks shown elsethread, but simply summing the sizes
of the elements and then using element-wise pointer arithmetic will
not do it. The problem will not show up on architectures that make
no strong alignment constraints, of course, and this includes the
usual x86 configurations.
--
In-Real-Life: Chris Torek, Wind River Systems (BSD engineering)
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://67.40.109.61/torek/index.html (for the moment)
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 13 '05 #19

P: n/a
The Real OS/2 Guy wrote:
RJH>> > If you must do it this way, the least clumsy way
RJH>> > I can think of that is guaranteed to work is to
RJH>> > make a union of the header and the record itself,
RJH>> > and allocate a bunch of those.
Now your union has the size of the biggest struct.


Correct. This is why I pointed out that efficiency might be an issue if the
structs were wildly different in size.
When the big struct
is 4 K, your header 20 bytes and the smallest struct is 16 bytes then
you needs more than 400 KB instead 20 + 16 * 100 = 1620 bytes when you
needs header + smallest struct [100].
But, as it turns out, the OP's header is slightly smaller than his struct,
so there is almost no waste of space, and the solution is much simpler than
any other so far proposed.
The idea is really bad.
Your assertion is noted. I disagree entirely with it. The idea of following
the advice slavishly is bad (for example, consider a very large header and
a comparatively small record), but in certain circumstances, including
those of the OP, it is a sensible strategy.

Understund how pointer arithmetic works and your memory usage is
thifty.
Parse error.

Always let the compiler think about alignment - it is its work
to do so.


It's the programmer's job to understand his program.

<snip>

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 13 '05 #20

P: n/a
Christian Bau <ch***********@cbau.freeserve.co.uk> wrote in message news:<ch*********************************@slb-newsm1.svr.pol.co.uk>...
In article <fe**************************@posting.google.com >,
bd******@hotmail.com (Bhalchandra Thatte) wrote:
Meanwhile I went to a book shop, and browsed through a book
(C interfaces or something like that by Hansen I think). He suggests

union Alignment {
int a;
long b;
float c;
double d;
void (*f)(void) fptr;
void* e;
...
}
He then uses sizeof(Alignment) and sizeof(header)
to calculate the offset.
I am still not comfortable with it. What if one missed
something in the union?


He missed pointer to short, int, long, long long and pointer to struct;
he missed long long as well. All the pointers that I mentioned could in
principle have different size and alignment requirements than void*.


I was trying to convey the main idea of the author, but errors
are mine. Probably the author didn't miss anything.
Is it sufficient to list all
basic types provided by the language?


On one very common architecture where sizeof (double) == 8, it would be
quite reasonable that structs with two consecutive double members have
alignment requirement of 16. And I cannot see anything in the C Standard
that would prevent this from happening.


This is the kind of thing that makes me uncomfortable with that idea.
But then it seems there is no easy general solution without wasting much space.
Thanks.
Nov 13 '05 #21

P: n/a
Richard Heathfield <do******@address.co.uk.invalid> wrote in message news:<bi**********@titan.btinternet.com>...
I am still not comfortable with it. What if one missed
something in the union? Is it sufficient to list all
basic types provided by the language?


No. For the alignment thing to be ***guaranteed*** to work on a general
basis, you must list every type used by the program, which includes all
user-defined types (which is why implementing a generalised leak detector
is much harder than it looks). It would be sufficient, in *your* case, to
include

struct header hdr;

and

struct record rcd;

into the alignment structure. But of course my solution doesn't require you
to include any of the other types (into your program, to solve your current
problem). A simple union of struct header and struct record is sufficient.


It won't work if I want to use the same pool for different applications.
Now I see why Knuth does it somewhat differently. He puts the header
at the end, (that is after the allocation for structs). Since the header is
fixed in all applications, you know its alignment requirement.
Based on his idea, probably I can do something like this:
(Errors in the following are of course mine, not Knuth's.)

struct header {
void* first;
header* next;
};

struct record {
....
}

/* to allocate for num records */
unsigned int n = sizeof(record)*num;
unsigned int s = sizeof(header);
unzigned int offset = (n%s) ? s - n%s : 0;
void* x = malloc(n + offset + s);
header* head = (header *) x+n+offset;
head->first = x;
head->next = ...

This is definitely better than putting the header in the
beginning of the block.

Thanks.
Nov 13 '05 #22

P: n/a
On Mon, 1 Sep 2003 18:02:07 UTC, Jack Klein <ja*******@spamcop.net>
wrote:
Consider:

================
#include <stdlib.h>

struct one { char ch; };
struct two { long l; };

char *fred = malloc(sizeof(one) + sizeof(two));

struct two *ptr2 = fred + sizeof(one);
is identical with:

strut one *o = (struct one *) fred;
ptr2 = (struct two*) (o +1),

When you put your compier in the sharpest warning level you needs the
casting. ALL warnings are really helpful! But when you knows exactly
what you does you can avoid the warning by saying the compiler: be
quirte, I know what I do.
long x = ptr2->l;
================

Code equivalent to the above will generate an alignment fault on some
architectures.


Never - except

struct two t2[2];
t2[1].l = 0;

gives the same exception - but then your compiler is buggy.

Each struct is defined on an aligned address - ever! You must do some
undefined pointer arithmetic to get an misaligned pointer.
See my other artikle for more details.


See ANSI/ISO/IEC 9899:1999 for accurate information.

--
Tschau/Bye
Herbert

eComStation 1.1 Deutsch Beta ist verügbar
Nov 13 '05 #23

P: n/a

On Mon, 1 Sep 2003, The Real OS/2 Guy wrote:

On Mon, 1 Sep 2003 18:02:07 UTC, Jack Klein wrote:
Consider: struct one { char ch; };
struct two { long l; };

char *fred = malloc(sizeof(one) + sizeof(two));

struct two *ptr2 = fred + sizeof(one);
is identical with:

struct one *o = (struct one *) fred;
struct two *ptr2 = (struct two*) (o + 1);


Modulo your typos, which I've fixed above, yes.
When you put your [compiler] in the sharpest warning level you [need]
the casting. ALL warnings are really helpful! But when you [know]
exactly what you [are doing] you can avoid the warning by saying [to]
the compiler: be [quiet], I know what I [am doing].
While this is also true, I don't see what casting has to do with
anything. As you said, the two code samples are basically equivalent.
Neither one contains any compiler error. Both contain undefined
behavior.
long x = ptr2->l;
================

Code equivalent to the above will generate an alignment fault on some
architectures.


Never - except

struct two t2[2];
t2[1].l = 0;

gives the same exception - but then your compiler is buggy.


That doesn't make any sense. My compiler is *not* buggy, and I don't
see any reason to suspect that Jack's is, either. The code above,
using t2[1], exhibits perfectly well-defined behavior. The code
that Jack posted, and the equivalent code that you posted, using
ptr2, exhibits undefined behavior.
Each struct is defined on an aligned address - [always]!
This is patently false. Consider again:

struct foo { char c; };
struct bar { int i; };

On many architectures, 'foo' will have an alignment restriction
of 1 or 2 bytes, and 'bar' will have an alignment restriction of
4 bytes. This is not theoretical.
You must do some
undefined pointer arithmetic to get an misaligned pointer.


True, but vacuous. Consider:

char c;
void *p = &c;
int *i = p;

Of course this is "undefined", and it's "pointer arithmetic",
but I don't think it's meaningful to call it "undefined pointer
arithmetic", since each operation is perfectly reasonable in
and of itself.
Replace the above with

struct foo c;
void *p = &c;
struct bar *i = p;

and you have the exact same problem - undefined behavior that
your average compiler won't be able to catch.

See ANSI/ISO/IEC 9899:1999 for accurate information.


Indeed.

-Arthur

Nov 13 '05 #24

P: n/a
In article <3F***********@mindspring.com>,
pete <pf*****@mindspring.com> wrote:
Christian Bau wrote:
On one very common architecture where sizeof (double) == 8,
it would be
quite reasonable that structs with two consecutive double members have
alignment requirement of 16.


What's the reason ?

What can a cpu do with a struct that has two double members,
when the the alignment requirements are for the size of the structure,
that a cpu can't can't do
when the structure alignment requirements are for the size of a member ?


Pentium 4, SSE2 instructions. Load a pair of double precision numbers
into a 16 byte register and know that the pair of doubles is correctly
aligned for this.
Nov 13 '05 #25

P: n/a
On Mon, 1 Sep 2003 20:37:50 UTC, Richard Heathfield
<do******@address.co.uk.invalid> wrote:
The Real OS/2 Guy wrote:
RJH>> > If you must do it this way, the least clumsy way
RJH>> > I can think of that is guaranteed to work is to
RJH>> > make a union of the header and the record itself,
RJH>> > and allocate a bunch of those.


Now your union has the size of the biggest struct.


Correct. This is why I pointed out that efficiency might be an issue if the
structs were wildly different in size.
When the big struct
is 4 K, your header 20 bytes and the smallest struct is 16 bytes then
you needs more than 400 KB instead 20 + 16 * 100 = 1620 bytes when you
needs header + smallest struct [100].


But, as it turns out, the OP's header is slightly smaller than his struct,
so there is almost no waste of space, and the solution is much simpler than
any other so far proposed.
The idea is really bad.


Your assertion is noted. I disagree entirely with it. The idea of following
the advice slavishly is bad (for example, consider a very large header and
a comparatively small record), but in certain circumstances, including
those of the OP, it is a sensible strategy.

Understund how pointer arithmetic works and your memory usage is
thifty.


Parse error.

Always let the compiler think about alignment - it is its work
to do so.


It's the programmer's job to understand his program.


And for that he has to know how pointer arithmetic works.

For that it is guaranteed that any struct of a given struct type has
equal size. Sou you can easy build single structs and struct arrays
dynamically and not only statically. It is guaranteed that each
pointer to each struct has the same size and aligned well.

sizeof(struct) gives you always the size of a struct. Adding this to a
pinter to char gives you always an well aligned address to start a new
struct - but native pointer arithmetic on the right type does it as
well.

I'd made the test not too long ago by writing an ANSI C program based
on that principe to get it in production on 5 different compilers in 5
different architectures - 16 and 32 bit, some of them were sensitive
against misalignment.
Written and debuged on ONE mashine (really insensitve against
misalignment), compiled and linked on all. Whereas I'd seen the
comilers of the four other mashines the first time as I had to start
to compile the program on that mashines. My knowledge of that mashines
was 0, zero, void at that time. As the program was tested well as I
started to port it nothing was to change.

The program was written completely without #ifdef, pure ANSI C.

Massive pointer arithmetic was needed to get all requiremts done - the
same as I'd desribed in the artikles before.

--
Tschau/Bye
Herbert

eComStation 1.1 Deutsch Beta ist verügbar
Nov 13 '05 #26

P: n/a
Bhalchandra Thatte wrote:
Richard Heathfield <do******@address.co.uk.invalid> wrote in message
news:<bi**********@titan.btinternet.com>...
But of course my solution doesn't require
you to include any of the other types (into your program, to solve your
current problem). A simple union of struct header and struct record is
sufficient.
It won't work if I want to use the same pool for different applications.


Very true, but that's new information. I've already explained that it won't
work well in the general case.
Now I see why Knuth does it somewhat differently. He puts the header
at the end, (that is after the allocation for structs).
Um, if it's a header, shouldn't it go at the fr... well, never mind. If it
makes you happy, by all means stick it at the back.
Since the header
is fixed in all applications, you know its alignment requirement.
How would you go about determining this, in a *portable* way? (This could
turn out to be a very interesting sub-thread.)
Based on his idea, probably I can do something like this:
(Errors in the following are of course mine, not Knuth's.)

struct header {
void* first;
header* next;
};

struct record {
...
}

/* to allocate for num records */
unsigned int n = sizeof(record)*num;
unsigned int s = sizeof(header);
unzigned int offset = (n%s) ? s - n%s : 0;
void* x = malloc(n + offset + s);
header* head = (header *) x+n+offset;
head->first = x;
head->next = ...

This is definitely better than putting the header in the
beginning of the block.


If you find it more convenient to put the header at the end, by all means do
so! :-)

It is not, however, a portable solution, and it may very well not work on
some platforms.
--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 13 '05 #27

P: n/a
The Real OS/2 Guy wrote:
On Mon, 1 Sep 2003 20:37:50 UTC, Richard Heathfield
<do******@address.co.uk.invalid> wrote:
The Real OS/2 Guy wrote:
> Always let the compiler think about alignment - it is its work
> to do so.
It's the programmer's job to understand his program.


And for that he has to know how pointer arithmetic works.


Yes. It's not difficult.
sizeof(struct) gives you always the size of a struct.


No, it gives you a syntax error.

I don't have time to continue this conversation. Please ask your C teacher
about syntax.

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 13 '05 #28

P: n/a
Richard Heathfield wrote:
The Real OS/2 Guy wrote:
RJH>> > If you must do it this way, the least clumsy way
RJH>> > I can think of that is guaranteed to work is to
RJH>> > make a union of the header and the record itself,
RJH>> > and allocate a bunch of those.


Now your union has the size of the biggest struct.


Correct. This is why I pointed out that efficiency might be an
issue if the structs were wildly different in size.
When the big struct is 4 K, your header 20 bytes and the
smallest struct is 16 bytes then you needs more than 400 KB
instead 20 + 16 * 100 = 1620 bytes when you needs header +
smallest struct [100].


But, as it turns out, the OP's header is slightly smaller than
his struct, so there is almost no waste of space, and the
solution is much simpler than any other so far proposed.


In addition, the explicit case of large header and small items
can be catered to by a struct containing the header and a pointer
to an array of small items. Allocation of this requires two
malloc calls, but all references can then be made via the header
alone. It also allows the luxury (or foolishness) of static
allocation of the header.

You can see an example of this in hashlib, available at:

<http://cbfalconer.home.att.net/download/>

which actually goes through three levels of allocation: the
header, a (variable) sized array of pointers, and a (variable)
sized item with no restrictions.

As Richard has pointed out, there is no substitute for
considering the data to be handled. This may actually require
thought.

--
Replies should be to the newsgroup
Chuck Falconer, on vacation.
Nov 13 '05 #29

P: n/a
pete wrote:
Bhalchandra Thatte wrote:

I am allocating a block of memory using malloc.
I want to use it to store a "header" structure
followed by structs in my application. How to calculate
the alignment without making any assumption
about the most restrictive type on my machine?


The memory returned by malloc is suitably aligned for
the most restrictive type on your machine.


Not true on IA-32 platforms, unless you "restrict" yourself to types which
are no more "restrictive" than double, and accept mis-aligned doubles as
"suitable" if you should happen to choose a malloc which aligns only ints.
--
Tim Prince
Nov 13 '05 #30

P: n/a
Tim Prince wrote:

pete wrote:

The memory returned by malloc is suitably aligned for
the most restrictive type on your machine.


Not true on IA-32 platforms,
unless you "restrict" yourself to types which
are no more "restrictive" than double,
and accept mis-aligned doubles as "suitable"
if you should happen to choose a malloc which aligns only ints.


Where are you going to get a malloc that only aligns ints ?

N869
7.20.3 Memory management functions
[#1] The order and contiguity of storage allocated by
successive calls to the calloc, malloc, and realloc
functions is unspecified. The pointer returned if the
allocation succeeds is suitably aligned so that it may be
assigned to a pointer to any type of object and then used to
access such an object or an array of such objects in the
space allocated

--
pete
Nov 13 '05 #31

P: n/a
LibraryUser <de**********@made.invalid> wrote:
Richard Heathfield wrote:
The Real OS/2 Guy wrote:
>> RJH>> > If you must do it this way, the least clumsy way
>> RJH>> > I can think of that is guaranteed to work is to
>> RJH>> > make a union of the header and the record itself,
>> RJH>> > and allocate a bunch of those.
>
> Now your union has the size of the biggest struct.


Correct. This is why I pointed out that efficiency might be an
issue if the structs were wildly different in size.
> When the big struct is 4 K, your header 20 bytes and the
> smallest struct is 16 bytes then you needs more than 400 KB
> instead 20 + 16 * 100 = 1620 bytes when you needs header +
> smallest struct [100].


But, as it turns out, the OP's header is slightly smaller than
his struct, so there is almost no waste of space, and the
solution is much simpler than any other so far proposed.


In addition, the explicit case of large header and small items
can be catered to by a struct containing the header and a pointer
to an array of small items. Allocation of this requires two
malloc calls, but all references can then be made via the header
alone. It also allows the luxury (or foolishness) of static
allocation of the header.


You don't need two malloc calls - you simply start the small item array
at the smallest multiple of the small item size that is larger than the
header size from the start of the malloc'ed region (and calculate a
suitable size to malloc in the first place).

- Kevin.

Nov 13 '05 #32

P: n/a
pete wrote:
Tim Prince wrote:

pete wrote:
> The memory returned by malloc is suitably aligned for
> the most restrictive type on your machine.


Not true on IA-32 platforms,
unless you "restrict" yourself to types which
are no more "restrictive" than double,
and accept mis-aligned doubles as "suitable"
if you should happen to choose a malloc which aligns only ints.


Where are you going to get a malloc that only aligns ints ?

As supplied with the most popular compilers for Windows.
N869
7.20.3 Memory management functions
[#1] The order and contiguity of storage allocated by
successive calls to the calloc, malloc, and realloc
functions is unspecified. The pointer returned if the
allocation succeeds is suitably aligned so that it may be
assigned to a pointer to any type of object and then used to
access such an object or an array of such objects in the
space allocated

"suitably aligned" is commonly taken as aligned on 4-byte boundaries for
Windows, and 8-byte boundaries for linux, although both OS support the same
data types, on the same hardware, one of which (not a std C data type)
requires 16-byte alignment. The hardware supports mis-aligned doubles, at
potentially great cost in performance. Thus, the definition of suitability
differs among implementations, with a different compromise between space
and performance.
--
Tim Prince
Nov 13 '05 #33

P: n/a
Kevin Easton wrote:
LibraryUser <de**********@made.invalid> wrote:
Richard Heathfield wrote:
The Real OS/2 Guy wrote:

>> RJH>> > If you must do it this way, the least clumsy way
>> RJH>> > I can think of that is guaranteed to work is to
>> RJH>> > make a union of the header and the record itself,
>> RJH>> > and allocate a bunch of those.
>
> Now your union has the size of the biggest struct.

Correct. This is why I pointed out that efficiency might be an
issue if the structs were wildly different in size.

> When the big struct is 4 K, your header 20 bytes and the
> smallest struct is 16 bytes then you needs more than 400 KB
> instead 20 + 16 * 100 = 1620 bytes when you needs header +
> smallest struct [100].

But, as it turns out, the OP's header is slightly smaller than
his struct, so there is almost no waste of space, and the
solution is much simpler than any other so far proposed.


In addition, the explicit case of large header and small items
can be catered to by a struct containing the header and a pointer
to an array of small items. Allocation of this requires two
malloc calls, but all references can then be made via the header
alone. It also allows the luxury (or foolishness) of static
allocation of the header.


You don't need two malloc calls - you simply start the small item
array at the smallest multiple of the small item size that is
larger than the header size from the start of the malloc'ed region
(and calculate a suitable size to malloc in the first place).


While you can play such foolish games, it is error prone and a
maintenance nightmare. It is also totally unnecessary.

--
Replies should be to the newsgroup
Chuck Falconer, on vacation.
Nov 13 '05 #34

P: n/a
LibraryUser <de**********@made.invalid> wrote:
Kevin Easton wrote:
LibraryUser <de**********@made.invalid> wrote: [...]
>
> In addition, the explicit case of large header and small items
> can be catered to by a struct containing the header and a pointer
> to an array of small items. Allocation of this requires two
> malloc calls, but all references can then be made via the header
> alone. It also allows the luxury (or foolishness) of static
> allocation of the header.


You don't need two malloc calls - you simply start the small item
array at the smallest multiple of the small item size that is
larger than the header size from the start of the malloc'ed region
(and calculate a suitable size to malloc in the first place).


While you can play such foolish games, it is error prone and a
maintenance nightmare. It is also totally unnecessary.


I don't believe it is either - the correct offset can be calculated
using sizeof so that it will continue to be correct after the object
sizes are changed, and I think it's more error-prone to use two mallocs
(and hence require two free()s).

- Kevin.
Nov 13 '05 #35

P: n/a
Kevin Easton wrote:
LibraryUser <de**********@made.invalid> wrote:
Kevin Easton wrote:
LibraryUser <de**********@made.invalid> wrote: [...] >
> In addition, the explicit case of large header and small items
> can be catered to by a struct containing the header and a pointer
> to an array of small items. Allocation of this requires two
> malloc calls, but all references can then be made via the header
> alone. It also allows the luxury (or foolishness) of static
> allocation of the header.

You don't need two malloc calls - you simply start the small item
array at the smallest multiple of the small item size that is
larger than the header size from the start of the malloc'ed region
(and calculate a suitable size to malloc in the first place).


While you can play such foolish games, it is error prone and a
maintenance nightmare. It is also totally unnecessary.


I don't believe it is either - the correct offset can be calculated
using sizeof so that it will continue to be correct after the object
sizes are changed, and I think it's more error-prone to use two mallocs
(and hence require two free()s).


IMNSHO the optimum method is to create two functions, something
like:

thing *creatething(size_t sizerequired);
void destroything(thing *thething);

which handle all the interrelationships and strictly limit any
error propagation. The application will then not need to know
anything about the organization of a thing, provided that
suitable functions are provided to operate on it. Once more, see
my hashlib package for an example.

--
Replies should be to the newsgroup
Chuck Falconer, on vacation.
Nov 13 '05 #36

P: n/a
Kevin Easton wrote:
LibraryUser <de**********@made.invalid> wrote:
Kevin Easton wrote:
LibraryUser <de**********@made.invalid> wrote: [...] >
> In addition, the explicit case of large header and small items
> can be catered to by a struct containing the header and a pointer
> to an array of small items. Allocation of this requires two
> malloc calls, but all references can then be made via the header
> alone. It also allows the luxury (or foolishness) of static
> allocation of the header.

You don't need two malloc calls - you simply start the small item
array at the smallest multiple of the small item size that is
larger than the header size from the start of the malloc'ed region
(and calculate a suitable size to malloc in the first place).


While you can play such foolish games, it is error prone and a
maintenance nightmare. It is also totally unnecessary.


I don't believe it is either - the correct offset can be calculated
using sizeof so that it will continue to be correct after the object
sizes are changed, and I think it's more error-prone to use two mallocs
(and hence require two free()s).


IMNSHO the optimum method is to create two functions, something
like:

thing *creatething(size_t sizerequired);
void destroything(thing *thething);

which handle all the interrelationships and strictly limit any
error propagation. The application will then not need to know
anything about the organization of a thing, provided that
suitable functions are provided to operate on it. Once more, see
my hashlib package for an example.

--
Replies should be to the newsgroup
Chuck Falconer, on vacation.
Nov 13 '05 #37

This discussion thread is closed

Replies have been disabled for this discussion.