In article <11amvh2$14pou$3@kst.eternal-september.org>,
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
cross@spitfire.i.gajendra.net (Dan Cross) writes:
In article <86v775h9o2.fsf@linuxsc.com>,
Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
cross@spitfire.i.gajendra.net (Dan Cross) writes:
[...]
I don't think this is true anymore, as of C23. Here's the
relevant text from n3220, sec 7.24.3, describing the return
value from `malloc` et al:
|The pointer returned if the allocation succeeds is suitably
|aligned so that it may be assigned to a pointer to any type of
|object with a fundamental alignment requirement and size less
|than or equal to the size requested.
This sentence is somewhat ambiguous because it's unclear whether
the "less than or equal to the size requested" criteria applies
to both the pointer type's size _and_ fundamental alignment
requirement, or _just_ the size, [...]
It's poorly constructed but in English it has only one
grammatical parse.
Nope. Not even close.
I think Tim is right about there being only one grammatical parse.
No, he is not. There are over a thousand ways to parse that
sentence "grammatically", [...]
In article <86v775h9o2.fsf@linuxsc.com>,
Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
cross@spitfire.i.gajendra.net (Dan Cross) writes:
In article <11al4mu$fqtl$1@kst.eternal-september.org>,
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
David Brown <david.brown@hesbynett.no> writes:
On 13/10/2026 10:38, chine.bleu wrote:
Tim Rentsch wrote:
sons[2] array. These links are basically pointers, but held
as uintptr_t so they can take one of the bits to mean "tall",
which means taller than the other subtree of the node. The
tree structure should maintain an invariant that at most one
Memory is cheap.
Not any more!
Do not encode tags into low bits of an address unless you really
know what your doing.
Agreed, as a principle.
As a precaution check the return address of malloc
p = malloc(m);
if ((uintptr_t)p)&1!=0) abort();
malloc always returns an address with suitable alignment for any
fundamental alignment on the target.
I don't think this is true anymore, as of C23. Here's the
relevant text from n3220, sec 7.24.3, describing the return
value from `malloc` et al:
|The pointer returned if the allocation succeeds is suitably
|aligned so that it may be assigned to a pointer to any type of
|object with a fundamental alignment requirement and size less
|than or equal to the size requested.
This sentence is somewhat ambiguous because it's unclear whether
the "less than or equal to the size requested" criteria applies
to both the pointer type's size _and_ fundamental alignment
requirement, or _just_ the size, [...]
It's poorly constructed but in English it has only one
grammatical parse.
Nope. Not even close.
cross@spitfire.i.gajendra.net (Dan Cross) writes:
In article <86v775h9o2.fsf@linuxsc.com>,
Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
cross@spitfire.i.gajendra.net (Dan Cross) writes:
In article <11al4mu$fqtl$1@kst.eternal-september.org>,
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
David Brown <david.brown@hesbynett.no> writes:
On 13/10/2026 10:38, chine.bleu wrote:
Tim Rentsch wrote:
sons[2] array. These links are basically pointers, but held
as uintptr_t so they can take one of the bits to mean "tall",
which means taller than the other subtree of the node. The
tree structure should maintain an invariant that at most one
Memory is cheap.
Not any more!
Do not encode tags into low bits of an address unless you really >>>>>>> know what your doing.
Agreed, as a principle.
As a precaution check the return address of malloc
p = malloc(m);
if ((uintptr_t)p)&1!=0) abort();
malloc always returns an address with suitable alignment for any
fundamental alignment on the target.
I don't think this is true anymore, as of C23. Here's the
relevant text from n3220, sec 7.24.3, describing the return
value from `malloc` et al:
|The pointer returned if the allocation succeeds is suitably
|aligned so that it may be assigned to a pointer to any type of
|object with a fundamental alignment requirement and size less
|than or equal to the size requested.
This sentence is somewhat ambiguous because it's unclear whether
the "less than or equal to the size requested" criteria applies
to both the pointer type's size _and_ fundamental alignment
requirement, or _just_ the size, [...]
It's poorly constructed but in English it has only one
grammatical parse.
Nope. Not even close.
I am confident my assessment is on fairly solid ground in this
case.
That said, I don't think there is any value in taking part in a
shouting match, which seems to be all you want to do here.
In article <11al4mu$fqtl$1@kst.eternal-september.org>,
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
David Brown <david.brown@hesbynett.no> writes:
On 13/10/2026 10:38, chine.bleu wrote:
Tim Rentsch wrote:
sons[2] array.ÿ These links are basically pointers, but heldMemory is cheap.
as uintptr_t so they can take one of the bits to mean "tall",
which means taller than the other subtree of the node.ÿ The
tree structure should maintain an invariant that at most one
Not any more!
Do not encode tags into low bits of an address unless you really
know what your doing.
Agreed, as a principle.
As a precaution check the return address of malloc
ÿÿÿÿp = malloc(m);
ÿÿÿÿif ((uintptr_t)p)&1!=0) abort();
malloc always returns an address with suitable alignment for any
fundamental alignment on the target.
I don't think this is true anymore, as of C23. Here's the
relevant text from n3220, sec 7.24.3, describing the return
value from `malloc` et al:
|The pointer returned if the allocation succeeds is suitably
|aligned so that it may be assigned to a pointer to any type of
|object with a fundamental alignment requirement and size less
|than or equal to the size requested.
This sentence is somewhat ambiguous because it's unclear whether
the "less than or equal to the size requested" criteria applies
to both the pointer type's size _and_ fundamental alignment
requirement, or _just_ the size, but I believe that it is the
former (that is, the "and" applies the size requirement to both
alignment and returned size). Thus, a conforming implementation
of `malloc(1)` could return a pointer that is `alignof(char)`,
but not `alignof(int)`.
I argue that examining the text from C17 and how it has changed
further supports this interpretation. From C17, sec 7.22.3:
|The pointer returned if the allocation succeeds is suitably
|aligned so that it may be assigned to a pointer to any type of
|object with a fundamental alignment requirement and then used
|to access such an object or an array of such objects in the
|space allocated (until the space is explicitly deallocated).
Here, no mention of the requested size is made at all, and this
clearly requires the return value from a successful allocation
by `malloc(1)` to be aligned so that one could assign it to a
pointer referring to any object of any type with a "fundamental
alignment requirement."
x[7] may be trampling on internal malloc bits.The allocator could allocate 7 byte (or smaller) objects in 8 byte
Playing games with pointer values can be useful for implementing
things like, e.g, Harris's lock-free linked list.
On 2026-10-13, Dan Cross <cross@spitfire.i.gajendra.net> wrote:
In article <11al4mu$fqtl$1@kst.eternal-september.org>,
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
David Brown <david.brown@hesbynett.no> writes:
On 13/10/2026 10:38, chine.bleu wrote:
Tim Rentsch wrote:
sons[2] array.ÿ These links are basically pointers, but heldMemory is cheap.
as uintptr_t so they can take one of the bits to mean "tall",
which means taller than the other subtree of the node.ÿ The
tree structure should maintain an invariant that at most one
Not any more!
Do not encode tags into low bits of an address unless you really
know what your doing.
Agreed, as a principle.
As a precaution check the return address of malloc
ÿÿÿÿp = malloc(m);
ÿÿÿÿif ((uintptr_t)p)&1!=0) abort();
malloc always returns an address with suitable alignment for any
fundamental alignment on the target.
I don't think this is true anymore, as of C23. Here's the
relevant text from n3220, sec 7.24.3, describing the return
value from `malloc` et al:
|The pointer returned if the allocation succeeds is suitably
|aligned so that it may be assigned to a pointer to any type of
|object with a fundamental alignment requirement and size less
|than or equal to the size requested.
This sentence is somewhat ambiguous because it's unclear whether
the "less than or equal to the size requested" criteria applies
to both the pointer type's size _and_ fundamental alignment
requirement, or _just_ the size, but I believe that it is the
former (that is, the "and" applies the size requirement to both
alignment and returned size). Thus, a conforming implementation
of `malloc(1)` could return a pointer that is `alignof(char)`,
but not `alignof(int)`.
Certainly a grammatic parse is possible such that the "less than or
equal" only applies to the size. But then it is saying "pointer any type
of object with a fundamental alignment requirement". That doesn't make
sense. We can regard all objects types as having an alignment
requirement (which may be relaxed: byte alignment). The mention of
alignment in this manner is redundant under this view. Or we can regard >those which have stricter than byte alignment as having a fundamental >alignment requirement. The above parse then doesn't make sense;
malloced pointers can be assigned to pointer types with byte alignment.
Either way it doesn't make a difference because ... ta daa ...
alignment is constrained by size. No type has an alignment requirement >exceeding its size: size being M, but required to be allocated on
an address divisible by N, where N > M.
So that is to say, if we state a requirement that the pointer
successfully returned out of an allocator for a request of size S
may be used as a pointer to any type whose size is <= S,
we need no additional wording about alignment! All such types
have an alignment necessarily <= S.
Then if we add wording that the pointer may be used to access
such an object, then that implies the alignment is good also;
we need not mention alignment.
If a pointer is good for accessing any type of object whose size is <=
S, then that pointer must be suitably aligned for any such type.
I argue that examining the text from C17 and how it has changed
further supports this interpretation. From C17, sec 7.22.3:
|The pointer returned if the allocation succeeds is suitably
|aligned so that it may be assigned to a pointer to any type of
|object with a fundamental alignment requirement and then used
|to access such an object or an array of such objects in the
|space allocated (until the space is explicitly deallocated).
Here, no mention of the requested size is made at all, and this
clearly requires the return value from a successful allocation
by `malloc(1)` to be aligned so that one could assign it to a
pointer referring to any object of any type with a "fundamental
alignment requirement."
"fundamental alignment requirement" is a normative term;
it refers to alignment <= _Alignof(max_align_t).
(An alignment that is larger would be something that the program
declares, not reflecting anything coming form the host machine.)
The requirement is saying that all successful mallocs (including
zero sized ones, if not returning null?) must be aligned for
a max_align_t, and may be accessed as such "in the space provided".
So malloc(7) can be converted to a pointer to something that has
8 byte alignment, but only the first 7 bytes of that can be
accessed.
For instance struct s { char x[7]; long long y; } could
be such a type on some platform. If long long has 8 byte alignment,
the structure type will have that alignment (and padding after x).
The result of malloc(7) may be converted to "struct s *",
and the pointer can be used to access p->x[0] through p->x[6].
x[7] may be trampling on internal malloc bits.
The allocator could allocate 7 byte (or smaller) objects in 8 byte
chunks with some flags packed in there.
Playing games with pointer values can be useful for implementing
things like, e.g, Harris's lock-free linked list.
But suppose you need two bits in a pointer, thus four byte alignment. It >would not make sense to rely on malloc(1) giving you pointers with two
bits to spare, yet what's what C17 was saying.
Of course, you're going to malloc at least four bytes, if you
want four byte alignment.
The allocator should be allowed to satisfy malloc(1) requests
out of a byte array (with a separately stored free bitmask
or radix tree for keeping track of free vs allocated bytes).
It doesn't make sense to require malloc(1) to provide max_align_t
alignment.
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
On 2026-10-18 10:42, Waldek Hebisch wrote:
[...]
I read the above as: "can access part of object that fits in
allocated space". That is important for structs and unions: you
clearly do not want to allocate memory for biggest union variant.
And I think that allocating memory only for used part of a struct
is pretty common.
Mind to explain that opinion?
If I define a (C-)'union' type I definitely want to store anything
possible in those unions, changing the value to another type as
necessary. - Mind the 'sizeof' of a union is [at least?] the size
of its largest component. - If I 'malloc' a union I use that size.
In cases where I want to use just one [smaller] component-type of
a union I just allocate that specific type not the union-type.
But maybe you meant something different?
I meant what I wrote.
C type system is too weak to give exact
type for more complicated data structure. Instead, real program
give approximate type and depend on holes in type system.
So you
have pointer to union and program is structured so that it only
accesses valid variant. Allocating memory for whole using may
waste a lot of memory and does not buy you any real safety:
accessing wrong variant is likely to lead to troubles regardless
of amount of memory that you allocated. And in case of
interesting data structures variant does not change after
creation (allocation). If you need different variant you simply
allocate new piece of memory.
BTW: Pascal 'new' for variant records takes extra argument
specifying requested variant. Corresponding pointer has type
'pointer to variant record', but legally can only be used with
the variant specified in call to 'new'. In C you get equivalent
effect (with essentially the same conditions) by allocating
amount of memory needed for specific variant of union, but
assigning 'malloc' result to pointer to union.
antispam@fricas.org (Waldek Hebisch) writes:
[I am responding to two postings, restoring a sentence that
was removed by an intermediate poster]
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
On 2026-10-18 10:42, Waldek Hebisch wrote:
[...]
I read the above as: "can access part of object that fits in
allocated space". That is important for structs and unions: you
clearly do not want to allocate memory for biggest union variant.
And I think that allocating memory only for used part of a struct
is pretty common.
I confess to being rather incredulous of these claims. More
below.
Mind to explain that opinion?
If I define a (C-)'union' type I definitely want to store anything
possible in those unions, changing the value to another type as
necessary. - Mind the 'sizeof' of a union is [at least?] the size
of its largest component. - If I 'malloc' a union I use that size.
In cases where I want to use just one [smaller] component-type of
a union I just allocate that specific type not the union-type.
But maybe you meant something different?
I meant what I wrote.
I think your alleged facts are wrong. The vast majority of C
programs, and the vast majority of C programmers, have no
interest in doing either of those things. If C code needs to use
some part of an allocated struct, a whole struct is allocated.
Evidence for this pattern can be seen in the common idiom for
calling malloc():
struct foo *pfoo = malloc( sizeof *pfoo );
The case for unions is even weaker. First it is unusual for a
union to have highly disparate sizes for its members; a factor
of two or four, maybe, but rarely more than that.
Furthermore if
it were important to access only a subset of the smaller members
then it is simple to create a new union type with only those
members. At some level it's necessary to do that to know what
size to give to malloc(). (And if it's only one member that is
meant to be accessed, then we expect to follow the above common
idiom for malloc() with a pointer to the member's type.)
Of course it is not impossible that there are C programs that
violate these norms. But they are at best few and far between,
and anyone who would write such programs runs a greatly increased
risk of undefined behavior. No sensible developer would do so.
In any case any use of such anti-patterns is so rare that it
wasn't a factor in deciding how malloc() is supposed to work.
C type system is too weak to give exact
type for more complicated data structure. Instead, real program
give approximate type and depend on holes in type system.
This idea is nonsense. The C type system is powerful enough to
express any type that C code can deal with.
So you
have pointer to union and program is structured so that it only
accesses valid variant. Allocating memory for whole using may
waste a lot of memory and does not buy you any real safety:
accessing wrong variant is likely to lead to troubles regardless
of amount of memory that you allocated. And in case of
interesting data structures variant does not change after
creation (allocation). If you need different variant you simply
allocate new piece of memory.
BTW: Pascal 'new' for variant records takes extra argument
specifying requested variant. Corresponding pointer has type
'pointer to variant record', but legally can only be used with
the variant specified in call to 'new'. In C you get equivalent
effect (with essentially the same conditions) by allocating
amount of memory needed for specific variant of union, but
assigning 'malloc' result to pointer to union.
Here we see the key to understanding the earlier comments: we
have someone who wants to write code in C but who wants to think
in Pascal. There is no reason to think the C standard means to
support the anti-patterns being advocated.
| Sysop: | Tetrazocine |
|---|---|
| Location: | Melbourne, VIC, Australia |
| Users: | 4 |
| Nodes: | 8 (0 / 8) |
| Uptime: | 190:54:48 |
| Calls: | 222 |
| Files: | 21,513 |
| Messages: | 85,912 |