A malloc question

W

Why Tea

What happens to the pointer below?

SomeStruct *p;
p = malloc(100*sizeof(SomeStruct)); /* without a cast */
return((void *)(p+1)); /* will the returned pointer point
to the 2nd struct? */

Seems to me there is no guarantee it will.

/Why Tea
 
J

jacob navia

Why Tea a écrit :
What happens to the pointer below?

SomeStruct *p;
p = malloc(100*sizeof(SomeStruct)); /* without a cast */
return((void *)(p+1)); /* will the returned pointer point
to the 2nd struct? */

Seems to me there is no guarantee it will.

/Why Tea

In my opinion it must point to p+1. Since p is a pointer
to SomeStruct, p+1 points to the second structure
in the table.
 
K

Kohn Emil Dan

Why Tea a écrit :

In my opinion it must point to p+1. Since p is a pointer
to SomeStruct, p+1 points to the second structure
in the table.

Assuming of course that a valid declaration of malloc() is in scope (e.g.
via #include <stdlib.h>), and the memory allocation succeeded. Otherwise,
the behavior is undefined.

Emil
 
P

Prasad J Pandit

Why said:
What happens to the pointer below?
SomeStruct *p;
p = malloc(100*sizeof(SomeStruct)); /* without a cast */
return((void *)(p+1)); /* will the returned pointer point
to the 2nd struct? */
Seems to me there is no guarantee it will.

Hello there,

The pointer arithmatic works according to the `type' of the pointer
`p'
that is `SomeStruct'.
So, the returned pointer should point to the 2'nd struct in the
dynamically
allocated array.
 
S

Scorpio

Why said:
What happens to the pointer below?

SomeStruct *p;
p = malloc(100*sizeof(SomeStruct)); /* without a cast */
return((void *)(p+1)); /* will the returned pointer point
to the 2nd struct? */

Seems to me there is no guarantee it will.

Yes, there is no guarantee. You did not check if your allocation is
successful or not before returning the pointer.
 
R

Richard Heathfield

Why Tea said:
What happens to the pointer below?

SomeStruct *p;
p = malloc(100*sizeof(SomeStruct)); /* without a cast */
return((void *)(p+1)); /* will the returned pointer point
to the 2nd struct? */

Seems to me there is no guarantee it will.

Provided you have a prototype in scope for malloc (i.e. you have included
<stdlib.h>), and provided malloc did not return NULL (which you do not
check), the returned pointer will indeed point to space properly aligned
for the SomeStruct type, at an offset of sizeof(SomeStruct) from the
beginning of the allocated block. This is guaranteed by the Standard
(subject to the caveats I mentioned).

It is never necessary or desirable to cast the value returned by malloc
(unless your name is P J Plauger, which, in your case, presumably it
isn't).
 
W

Why Tea

It is never necessary or desirable to cast the value returned by malloc
(unless your name is P J Plauger, which, in your case, presumably it
isn't).

Thanks for the answer. No, I', not P J :), so no cast for me...

One more question while I'm at it about the memory stuff. Assuming I
have the following code:

SomeStruct *p;
p = malloc(100 + sizeof(SomeStruct)); /* 100 is not multiples of
sizeof(SomeStruct) */
/* do something before freeing it */
free(p);

Will the entire memory pointed to by p be released? Does free(p) always
releases multiples of the data structure p points to?
 
R

Richard Heathfield

Why Tea said:

One more question while I'm at it about the memory stuff. Assuming I
have the following code:

SomeStruct *p;
p = malloc(100 + sizeof(SomeStruct)); /* 100 is not multiples of
sizeof(SomeStruct) */
/* do something before freeing it */
free(p);

Will the entire memory pointed to by p be released? Does free(p) always
releases multiples of the data structure p points to?

malloc() doesn't allocate data structures. It simply allocates a block of
memory, n bytes in size (where you supply n), and returns a pointer to the
start of that block. In this case, you calculate n like this: 100 +
sizeof(SomeStruct). But malloc doesn't see that calculation. It only sees
the result. It doesn't know about SomeStruct, let alone sizeof(SomeStruct).
It only sees 123, or 145, or whatever it is that 100+sizeof(SomeStruct)
evaluates to. It will try to allocate that much memory, and return a
pointer to that memory if successful.

When you pass that pointer value to free(), the whole block is freed, and
the pointer value becomes indeterminate.
 
R

Richard Tobin

Why Tea said:
p = malloc(100 + sizeof(SomeStruct)); /* 100 is not multiples of sizeof(SomeStruct) */
/* do something before freeing it */

Be sure you know what you're doing here. You can't, for example,
reliably store 100 chars followed by a struct in this memory, because
the alignment of p+100 may not be suitable for the struct.

-- Richard
 
W

Why Tea

Richard said:
Be sure you know what you're doing here. You can't, for example,
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?
 
E

Eric Sosman

Why said:
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 ...
 
G

Guest

Why said:
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 in SomeStruct are included in the result of sizeof, but
what happens if UserStruct has stricter alignment requirements than
SomeStruct? Consider

struct SS {
char x;
};
struct US {
long x;
};

sizeof(struct SS) is probably one, but dynamically allocating memory
and storing a struct US one byte after an aligned address is not likely
to work.

(Technically, I believe the all structures are required to have the
same alignment. In practice, they don't, and shouldn't.)
 
E

Eric Sosman

Harald said:
[...]
(Technically, I believe the all structures are required to have the
same alignment. In practice, they don't, and shouldn't.)

You're probably thinking about pointers to structs, not
about structs. All pointers to all types of structs have the
same representation and alignment requirements, but that's
just the pointer itself: The thing it points to has its own
idiosyncratic alignment and representation.
 
G

Guest

Eric said:
Harald said:
[...]
(Technically, I believe the all structures are required to have the
same alignment. In practice, they don't, and shouldn't.)

You're probably thinking about pointers to structs, not
about structs. All pointers to all types of structs have the
same representation and alignment requirements, but that's
just the pointer itself: The thing it points to has its own
idiosyncratic alignment and representation.

I am talking about structures. Pointers to structures, as you mention,
have the same representation. The same representation means the same
possible values. (If you disagree, could you explain what is meant by
6.10.1p3? "For the purposes of this [#if expressions] token conversion
and evaluation, all signed integer types and all unsigned integer types
act as if they have the same representation as, respectively, the types
intmax_t and uintmax_t deï¬ned in the header <stdint.h>.142)") The
same possible values for pointers to structures means the same
alignment for the actual structures.
 
R

Richard Tobin

Why Tea said:
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?

No. The padding inside SomeStruct and UserStruct are included in there
sizes, but you may need padding *between* them which is not part of
either.

If you know the structs, I think the simplest thing to do is declare
a third struct containing them:

struct mystruct {SomeStruct a; UserStruct b;} *p;

and allocate sizeof(*p).

-- Richard
 
E

Eric Sosman

Harald said:
Eric said:
Harald said:
[...]
(Technically, I believe the all structures are required to have the
same alignment. In practice, they don't, and shouldn't.)
You're probably thinking about pointers to structs, not
about structs. All pointers to all types of structs have the
same representation and alignment requirements, but that's
just the pointer itself: The thing it points to has its own
idiosyncratic alignment and representation.

I am talking about structures. Pointers to structures, as you mention,
have the same representation. The same representation means the same
possible values. (If you disagree, could you explain what is meant by
6.10.1p3? "For the purposes of this [#if expressions] token conversion
and evaluation, all signed integer types and all unsigned integer types
act as if they have the same representation as, respectively, the types
intmax_t and uintmax_t deï¬ned in the header <stdint.h>.142)") The
same possible values for pointers to structures means the same
alignment for the actual structures.

The quoted section doesn't seem to have much to do with
pointers, but I agree that all struct pointers have the same
representation (because the Standard says so, in 6.2.5/26).

However, a shared representation does not imply a common
universe of values! The value of a representation depends on
the type of the expression that accesses it. A particular
representation R (a "bit pattern," if that's more down-to-earth)
may be a value for a `struct S*' but a trap representation for a
`struct T*'. A pointer representation that doesn't satisfy the
alignment requirements of the pointed-to type is not a value
(in the sense that C uses the term) but a trap representation.

Note that "trap representation" does not imply that a trap
will necessarily occur on all attempted uses of the non-value.
Section 6.2.6.1/5 merely says that the behavior is undefined if
a trap representation is treated as a value. In particular, it
may be possible to perform arithmetic on an improperly-aligned
pointer in order to derive one that is properly aligned -- but
then again, it may not be.
 
R

Richard Tobin

If you know the structs, I think the simplest thing to do is declare
a third struct containing them:

On the other hand, if you *don't* know the structs (which after rereading
your message I think is the situation), you will have more trouble.
Of course, in that case you don't know how much space to allocate.
Does the user pass in the size? Or are you just telling them there's
100 bytes available?

There are various tricks that give you a fairly reliable maximum
required alignment, but perhaps it might be better to re-order the
structures, and put the user one first. Then you can declare

struct mystruct {char space[100]; SomeStruct a;} *p;

-- Richard
 
G

Guest

Eric said:
Harald said:
Eric said:
Harald van Dijk wrote:
[...]
(Technically, I believe the all structures are required to have the
same alignment. In practice, they don't, and shouldn't.)
You're probably thinking about pointers to structs, not
about structs. All pointers to all types of structs have the
same representation and alignment requirements, but that's
just the pointer itself: The thing it points to has its own
idiosyncratic alignment and representation.

I am talking about structures. Pointers to structures, as you mention,
have the same representation. The same representation means the same
possible values. (If you disagree, could you explain what is meant by
6.10.1p3? "For the purposes of this [#if expressions] token conversion
and evaluation, all signed integer types and all unsigned integer types
act as if they have the same representation as, respectively, the types
intmax_t and uintmax_t deï¬ned in the header <stdint.h>.142)") The
same possible values for pointers to structures means the same
alignment for the actual structures.

The quoted section doesn't seem to have much to do with
pointers, but I agree that all struct pointers have the same
representation (because the Standard says so, in 6.2.5/26).

However, a shared representation does not imply a common
universe of values!

You're right that 6.10.1p3 doesn't have anything to do with struct
pointers, but it clarifies what "same representation" implies. So, if
you believe it doesn't imply the same set of values, what do you think
the quoted sentence of 6.10.1p3 means?
 
W

Why Tea

Eric said:
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?

Based on the assumption above, if we were to assume the stricter
UserStruct comes first, will it avoid the problem?

/Why Tea
 
G

Guest

Why said:
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.
 

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

A malloc question, part 2 25
Alternative to Malloc in C 0
malloc 40
Naive Custom Malloc Implementation 8
array-size/malloc limit and strlen() failure 26
malloc 33
malloc() and implicit cast 49
Malloc question 9

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top