Re: A malloc question
- From: "Harald van Dijk" <truedfx@xxxxxxxxx>
- Date: 28 Dec 2006 14:58:44 -0800
Why Tea wrote:
Eric Sosman wrote:
Why Tea wrote:
Richard Tobin wrote:
In article <1167319643.682777.100860@xxxxxxxxxxxxxxxxxxxxxxxxxxx>,
Why Tea <ytlim1@xxxxxxxxx> wrote:
p = malloc(100 + sizeof(SomeStruct)); /* 100 is not multiples of sizeof(SomeStruct) */Be sure you know what you're doing here. You can't, for example,
/* do something before freeing it */
reliably store 100 chars followed by a struct in this memory, because
the alignment of p+100 may not be suitable for the struct.
Thanks Richard. In fact I was reading someone else's code. The
intention of the code is to have a memory allocation similar to this:
|<- SomeStruct ->|<- UserStruct ->
Hence,
SomeStruct *p;
p = malloc(sizeof(SomeStruct) + sizeof(UserStruct)); /* UserStruct can
be anything */
...
free(p);
(p+1) points to the beginning of UserStruct, so users can store
anything in there.
My understanding is, the paddings (if any) for memory alignment are
included in the calculation of sizeof(). So the code should work
properly. Is my understanding correct?
Padding bytes are part of the struct, and so are included
in the sizeof count. But that doesn't solve the problem of
getting proper alignment for the UserStruct part! Imagine
typedef struct { int x; } SomeStruct;
typedef struct { double y; } UserStruct;
and suppose (1) that there are no padding bytes, (2) that an
int occupies four bytes and must be aligned on a four-byte
boundary, and (3) that a double occupies eight bytes and must
be aligned on an eight-byte boundary. Then the code above will
request twelve bytes, and the allocated memory will begin on an
eight-byte boundary (because the memory returned by malloc() is
properly aligned for any use whatever, hence it's aligned at
least as strictly as a double would require). If p points to
an eight-byte boundary, then p+1 points four bytes further
along, to a four-byte boundary that is not an eight-byte
boundary, and a UserStruct can't begin there.
Things will work all right if UserStruct's alignment is no
stricter than SomeStruct's, but there's no a priori way to know
that this is true. If the actual type of UserStruct is known
(and not just its size), the simplest approach may be
struct { SomeStruct s; UserStruct u; } *p;
p = malloc(sizeof *p);
if (p == NULL) ...
p->s.x = 42;
p->u.y = 42.0;
...
free (p);
In a situation where only sizeof(UserStruct) is known and
not its actual type, a traditional but slightly iffy approach
is to try to figure out what the strictest alignment is:
typedef struct {
int i; long l; long long ll;
float f; double d; long double ld;
char *cp; int *ip; long *lp; long long *llp;
float *fp; double *dp; long double *ldp;
struct whocares *sp;
union whoknows *up;
void (*funcp)(void);
} Worst;
#define PADDED(n) ( ((n) + sizeof(Worst) - 1) \
/ sizeof(Worst) * sizeof(Worst) )
SomeStruct *p = malloc(PADDED(sizeof(SomeStruct))
+ size_of_user_struct);
if (p == NULL) ...
/* Now p points to the SomeStruct, and
* (char*)p + PADDED(sizeof(SomeStruct))
* points to the UserStruct
*/
One drawback to this approach is that it may overestimate
the strictness of UserStruct's alignment. Another is that it's
not possible to enumerate all possible types in the Worst
definition ...
Eric, thanks for the very detailed answer. But there is still something
that is not clear to me.
Suppose the following:
sizeof(SomeStruct) = 8
sizeof(UserStruct) = 16
malloc() will see a request of 24 byte allocation. How does it work out
whether alignment is at 4 byte, 8 byte or 16 byte boundary?
malloc doesn't work this out. It always allocates maximally aligned
blocks of memory. (Keep in mind that a 16-byte aligned block is also
8-byte and 4-byte aligned.) What "maximally aligned" is depends on your
processor and operating system, not on your program, so this only has
to be determined once, and that is when your implementation of the
standard library was written.
Based on the assumption above, if we were to assume the stricter
UserStruct comes first, will it avoid the problem?
Unfortunately, it won't, since it's also just as possible that
SomeStruct has stricter alignment requirements.
.
- References:
- A malloc question
- From: Why Tea
- Re: A malloc question
- From: Richard Heathfield
- Re: A malloc question
- From: Why Tea
- Re: A malloc question
- From: Richard Tobin
- Re: A malloc question
- From: Why Tea
- Re: A malloc question
- From: Eric Sosman
- Re: A malloc question
- From: Why Tea
- A malloc question
- Prev by Date: Re: A malloc question
- Next by Date: Re: does the file extension matter how it's compiled?
- Previous by thread: Re: A malloc question
- Next by thread: Re: A malloc question
- Index(es):
Relevant Pages
|