Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #138077 > unrolled thread
| Started by | Anton Shepelev <anton.txt@gmail.com> |
|---|---|
| First post | 2018-11-17 14:38 +0300 |
| Last post | 2018-11-19 14:33 -0800 |
| Articles | 20 on this page of 134 — 18 participants |
Back to article view | Back to comp.lang.c
Pointer conversion and alignment Anton Shepelev <anton.txt@gmail.com> - 2018-11-17 14:38 +0300
Re: Pointer conversion and alignment Anton Shepelev <anton.txt@gmail.com> - 2018-11-17 17:37 +0300
Re: Pointer conversion and alignment Ben Bacarisse <ben.usenet@bsb.me.uk> - 2018-11-17 21:01 +0000
Re: Pointer conversion and alignment Anton Shepelev <anton.txt@gmail.com> - 2018-11-18 00:43 +0300
Re: Pointer conversion and alignment Anton Shepelev <anton.txt@gmail.com> - 2018-11-18 01:20 +0300
Re: Pointer conversion and alignment Richard Damon <Richard@Damon-Family.org> - 2018-11-17 18:12 -0500
Re: Pointer conversion and alignment Anton Shepelev <anton.txt@gmail.com> - 2018-11-18 02:32 +0300
Re: Pointer conversion and alignment Richard Damon <Richard@Damon-Family.org> - 2018-11-17 18:59 -0500
Re: Pointer conversion and alignment Anton Shepelev <anton.txt@gmail.com> - 2018-11-18 12:40 +0300
Re: Pointer conversion and alignment Ben Bacarisse <ben.usenet@bsb.me.uk> - 2018-11-18 02:14 +0000
Re: Pointer conversion and alignment Anton Shepelev <anton.txt@gmail.com> - 2018-11-18 13:23 +0300
Re: Pointer conversion and alignment Ben Bacarisse <ben.usenet@bsb.me.uk> - 2018-11-18 11:28 +0000
Re: Pointer conversion and alignment Anton Shepelev <anton.txt@gmail.com> - 2018-11-18 15:31 +0300
Re: Pointer conversion and alignment Ben Bacarisse <ben.usenet@bsb.me.uk> - 2018-11-18 15:03 +0000
Re: Pointer conversion and alignment Anton Shepelev <anton.txt@gmail.com> - 2018-11-18 23:00 +0300
Re: Pointer conversion and alignment Anton Shepelev <anton.txt@gmail.com> - 2018-11-18 00:49 +0300
Re: Pointer conversion and alignment Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2018-11-17 06:52 -0800
Re: Pointer conversion and alignment Ian Collins <ian-news@hotmail.com> - 2018-11-18 09:18 +1300
Re: Pointer conversion and alignment Keith Thompson <kst-u@mib.org> - 2018-11-17 13:49 -0800
Re: Pointer conversion and alignment Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2018-11-17 13:57 -0800
Re: Pointer conversion and alignment Ian Collins <ian-news@hotmail.com> - 2018-11-18 11:08 +1300
Re: Pointer conversion and alignment Anton Shepelev <anton.txt@gmail.com> - 2018-11-18 01:13 +0300
Re: Pointer conversion and alignment Keith Thompson <kst-u@mib.org> - 2018-11-17 18:37 -0800
Re: Pointer conversion and alignment Philipp Klaus Krause <pkk@spth.de> - 2018-11-18 14:14 +0100
Re: Pointer conversion and alignment Richard Damon <Richard@Damon-Family.org> - 2018-11-17 10:05 -0500
Re: Pointer conversion and alignment Anton Shepelev <anton.txt@gmail.com> - 2018-11-18 01:08 +0300
Re: Pointer conversion and alignment "Chris M. Thomasson" <invalid_chris_thomasson@invalid.invalid> - 2018-11-17 14:31 -0800
Re: Pointer conversion and alignment "Chris M. Thomasson" <invalid_chris_thomasson@invalid.invalid> - 2018-11-17 16:10 -0800
Re: Pointer conversion and alignment Anton Shepelev <anton.txt@gmail.com> - 2018-11-18 15:01 +0300
Re: Pointer conversion and alignment James Kuyper <jameskuyper@alumni.caltech.edu> - 2018-11-18 07:25 -0500
Re: Pointer conversion and alignment "Chris M. Thomasson" <invalid_chris_thomasson@invalid.invalid> - 2018-11-19 21:30 -0800
Re: Pointer conversion and alignment "Chris M. Thomasson" <invalid_chris_thomasson@invalid.invalid> - 2018-11-20 14:20 -0800
Re: Pointer conversion and alignment Richard Damon <Richard@Damon-Family.org> - 2018-11-17 18:04 -0500
Re: Pointer conversion and alignment Philipp Klaus Krause <pkk@spth.de> - 2018-11-18 14:18 +0100
Re: Pointer conversion and alignment scott@slp53.sl.home (Scott Lurndal) - 2018-11-18 19:49 +0000
Re: Pointer conversion and alignment Tim Rentsch <txr@alumni.caltech.edu> - 2018-11-23 18:27 -0800
Re: Pointer conversion and alignment Richard Damon <Richard@Damon-Family.org> - 2018-11-23 21:59 -0500
Re: Pointer conversion and alignment Tim Rentsch <txr@alumni.caltech.edu> - 2018-11-24 00:32 -0800
Re: Pointer conversion and alignment Richard Damon <Richard@Damon-Family.org> - 2018-11-24 08:17 -0500
Re: Pointer conversion and alignment Tim Rentsch <txr@alumni.caltech.edu> - 2018-11-29 09:55 -0800
Re: Pointer conversion and alignment Richard Damon <Richard@Damon-Family.org> - 2018-11-29 21:48 -0500
Re: Pointer conversion and alignment Tim Rentsch <txr@alumni.caltech.edu> - 2018-12-05 04:14 -0800
Re: Pointer conversion and alignment Richard Damon <Richard@Damon-Family.org> - 2018-12-05 08:14 -0500
Re: Pointer conversion and alignment Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2018-12-05 05:29 -0800
Re: Pointer conversion and alignment David Brown <david.brown@hesbynett.no> - 2018-12-05 14:44 +0100
Re: Pointer conversion and alignment Richard Damon <Richard@Damon-Family.org> - 2018-12-05 21:58 -0500
Re: Pointer conversion and alignment Anton Shepelev <anton.txt@g{oogle}mail.com> - 2018-12-05 16:38 +0300
Re: Pointer conversion and alignment scott@slp53.sl.home (Scott Lurndal) - 2018-12-05 14:23 +0000
Re: Pointer conversion and alignment Keith Thompson <kst-u@mib.org> - 2018-12-05 14:35 -0800
Re: Pointer conversion and alignment Tim Rentsch <txr@alumni.caltech.edu> - 2018-12-08 19:28 -0800
Re: Pointer conversion and alignment Richard Damon <Richard@Damon-Family.org> - 2018-12-09 08:18 -0500
Re: Pointer conversion and alignment Richard Damon <Richard@Damon-Family.org> - 2018-12-09 14:35 -0500
Re: Pointer conversion and alignment Keith Thompson <kst-u@mib.org> - 2018-12-09 14:04 -0800
Re: Pointer conversion and alignment Richard Damon <Richard@Damon-Family.org> - 2018-12-09 20:40 -0500
Re: Pointer conversion and alignment Tim Rentsch <txr@alumni.caltech.edu> - 2018-12-17 07:18 -0800
Re: Pointer conversion and alignment Keith Thompson <kst-u@mib.org> - 2018-12-17 12:35 -0800
Re: Pointer conversion and alignment Tim Rentsch <txr@alumni.caltech.edu> - 2018-12-17 12:48 -0800
Re: Pointer conversion and alignment "Chris M. Thomasson" <invalid_chris_thomasson@invalid.invalid> - 2018-11-24 18:33 -0800
My dynamic arrays module [was:Re: Pointer conversion and alignment] Anton Shepelev <anton.txt@gmail.com> - 2018-11-19 02:26 +0300
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Ben Bacarisse <ben.usenet@bsb.me.uk> - 2018-11-19 11:08 +0000
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Anton Shepelev <anton.txt@g{oogle}mail.com> - 2018-11-19 15:37 +0300
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Anton Shepelev <anton.txt@g{oogle}mail.com> - 2018-11-19 15:39 +0300
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Ben Bacarisse <ben.usenet@bsb.me.uk> - 2018-11-19 15:07 +0000
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Anton Shepelev <anton.txt@gmail.com> - 2018-11-19 22:24 +0300
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] jameskuyper@alumni.caltech.edu - 2018-11-19 12:33 -0800
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Anton Shepelev <anton.txt@gmail.com> - 2018-11-20 00:34 +0300
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] jameskuyper@alumni.caltech.edu - 2018-11-19 14:38 -0800
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Ben Bacarisse <ben.usenet@bsb.me.uk> - 2018-11-20 00:43 +0000
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] James Kuyper <jameskuyper@alumni.caltech.edu> - 2018-11-19 21:44 -0500
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] jadill33@gmail.com - 2018-11-20 07:11 -0800
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] bart4858@gmail.com - 2018-11-20 10:02 -0800
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Ben Bacarisse <ben.usenet@bsb.me.uk> - 2018-11-19 22:20 +0000
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Anton Shepelev <anton.txt@g{oogle}mail.com> - 2018-11-20 14:01 +0300
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Melzzzzz <Melzzzzz@zzzzz.com> - 2018-11-20 11:07 +0000
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Anton Shepelev <anton.txt@g{oogle}mail.com> - 2018-11-20 15:12 +0300
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] James Kuyper <jameskuyper@alumni.caltech.edu> - 2018-11-20 08:15 -0500
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Anton Shepelev <anton.txt@gmail.com> - 2018-11-20 23:08 +0300
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] jameskuyper@alumni.caltech.edu - 2018-11-20 14:13 -0800
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Anton Shepelev <anton.txt@g{oogle}mail.com> - 2018-11-21 16:38 +0300
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] James Kuyper <jameskuyper@alumni.caltech.edu> - 2018-11-21 09:05 -0500
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Anton Shepelev <anton.txt@g{oogle}mail.com> - 2018-11-21 20:28 +0300
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] jameskuyper@alumni.caltech.edu - 2018-11-21 12:58 -0800
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Anton Shepelev <anton.txt@gmail.com> - 2018-11-22 01:47 +0300
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] jameskuyper@alumni.caltech.edu - 2018-11-21 15:50 -0800
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Anton Shepelev <anton.txt@gmail.com> - 2018-11-24 19:37 +0300
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Ben Bacarisse <ben.usenet@bsb.me.uk> - 2018-11-21 21:22 +0000
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Ben Bacarisse <ben.usenet@bsb.me.uk> - 2018-11-21 01:15 +0000
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Ben Bacarisse <ben.usenet@bsb.me.uk> - 2018-11-19 15:06 +0000
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] mark.bluemel@gmail.com - 2018-11-19 08:05 -0800
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] scott@slp53.sl.home (Scott Lurndal) - 2018-11-19 16:49 +0000
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] jameskuyper@alumni.caltech.edu - 2018-11-19 10:35 -0800
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Anton Shepelev <anton.txt@gmail.com> - 2018-11-20 00:45 +0300
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] jameskuyper@alumni.caltech.edu - 2018-11-19 14:24 -0800
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Anton Shepelev <anton.txt@g{oogle}mail.com> - 2018-11-20 15:05 +0300
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] James Kuyper <jameskuyper@alumni.caltech.edu> - 2018-11-20 08:31 -0500
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Richard Damon <Richard@Damon-Family.org> - 2018-11-20 20:02 -0500
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Anton Shepelev <anton.txt@gmail.com> - 2018-11-21 22:47 +0300
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] jameskuyper@alumni.caltech.edu - 2018-11-21 13:08 -0800
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Anton Shepelev <anton.txt@gmail.com> - 2018-11-22 00:31 +0300
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Ben Bacarisse <ben.usenet@bsb.me.uk> - 2018-11-21 21:36 +0000
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Anton Shepelev <anton.txt@g{oogle}mail.com> - 2018-11-19 16:04 +0300
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Ben Bacarisse <ben.usenet@bsb.me.uk> - 2018-11-19 14:56 +0000
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Anton Shepelev <anton.txt@gmail.com> - 2018-11-24 19:24 +0300
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Ben Bacarisse <ben.usenet@bsb.me.uk> - 2018-11-24 21:31 +0000
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Ben Bacarisse <ben.usenet@bsb.me.uk> - 2018-11-24 21:46 +0000
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Anton Shepelev <anton.txt@gmail.com> - 2018-11-25 01:12 +0300
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Ben Bacarisse <ben.usenet@bsb.me.uk> - 2018-11-25 01:39 +0000
Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] Anton Shepelev <anton.txt@gmail.com> - 2018-11-25 14:19 +0300
Re: Pointer conversion and alignment jadill33@gmail.com - 2018-11-19 08:44 -0800
Re: Pointer conversion and alignment Anton Shepelev <anton.txt@gmail.com> - 2018-11-20 00:02 +0300
Re: Pointer conversion and alignment Keith Thompson <kst-u@mib.org> - 2018-11-19 13:51 -0800
Re: Pointer conversion and alignment Anton Shepelev <anton.txt@gmail.com> - 2018-11-20 01:08 +0300
Re: Pointer conversion and alignment jameskuyper@alumni.caltech.edu - 2018-11-19 14:31 -0800
Re: Pointer conversion and alignment Anton Shepelev <anton.txt@g{oogle}mail.com> - 2018-11-20 15:21 +0300
Re: Pointer conversion and alignment James Kuyper <jameskuyper@alumni.caltech.edu> - 2018-11-20 08:59 -0500
Re: Pointer conversion and alignment Keith Thompson <kst-u@mib.org> - 2018-11-20 11:06 -0800
Re: Pointer conversion and alignment jameskuyper@alumni.caltech.edu - 2018-11-20 12:43 -0800
Re: Pointer conversion and alignment Keith Thompson <kst-u@mib.org> - 2018-11-20 14:33 -0800
Re: Pointer conversion and alignment Anton Shepelev <anton.txt@g{oogle}mail.com> - 2018-11-21 14:33 +0300
Re: Pointer conversion and alignment Richard Damon <Richard@Damon-Family.org> - 2018-11-21 07:49 -0500
Re: Pointer conversion and alignment Keith Thompson <kst-u@mib.org> - 2018-11-21 12:42 -0800
Re: Pointer conversion and alignment James Kuyper <jameskuyper@alumni.caltech.edu> - 2018-11-21 08:41 -0500
Re: Pointer conversion and alignment Anton Shepelev <anton.txt@gmail.com> - 2018-11-25 15:06 +0300
Re: Pointer conversion and alignment James Kuyper <jameskuyper@alumni.caltech.edu> - 2018-11-25 10:47 -0500
Re: Pointer conversion and alignment Anton Shepelev <anton.txt@g{oogle}mail.com> - 2018-11-26 12:42 +0300
Re: Pointer conversion and alignment Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2018-11-26 03:07 -0800
Re: Pointer conversion and alignment Keith Thompson <kst-u@mib.org> - 2018-11-26 12:56 -0800
Re: Pointer conversion and alignment Richard Damon <Richard@Damon-Family.org> - 2018-11-26 18:17 -0500
Re: Pointer conversion and alignment jameskuyper@alumni.caltech.edu - 2018-11-26 09:06 -0800
Re: Pointer conversion and alignment Anton Shepelev <anton.txt@gmail.com> - 2018-11-26 23:52 +0300
Re: Pointer conversion and alignment jameskuyper@alumni.caltech.edu - 2018-11-26 13:13 -0800
Re: Pointer conversion and alignment Anton Shepelev <anton.txt@gmail.com> - 2018-11-27 00:31 +0300
Re: Pointer conversion and alignment jameskuyper@alumni.caltech.edu - 2018-11-26 14:15 -0800
Re: Pointer conversion and alignment jadill33@gmail.com - 2018-11-19 14:33 -0800
Page 3 of 7 — ← Prev page 1 2 [3] 4 5 6 7 Next page →
| From | Richard Damon <Richard@Damon-Family.org> |
|---|---|
| Date | 2018-11-29 21:48 -0500 |
| Message-ID | <ay1MD.253724$TK1.180494@fx19.iad> |
| In reply to | #138404 |
On 11/29/18 12:55 PM, Tim Rentsch wrote:
> Richard Damon <Richard@Damon-Family.org> writes:
>
>> On 11/24/18 3:32 AM, Tim Rentsch wrote:
>>
>>> Richard Damon <Richard@Damon-Family.org> writes:
>>>
>>>> On 11/23/18 9:27 PM, Tim Rentsch wrote:
>>>>
>>>>> Richard Damon <Richard@Damon-Family.org> writes:
>>>>>
>>>>>> In general, malloc and family will return pointers that are
>>>>>> aligned to the most strict alignment required by the system.
>>>>>> While it is possible that it could give less strict alignment
>>>>>> for small allocations, [...]
>>>>>
>>>>> My understanding is that such an implementation would not be
>>>>> conforming. Return values from malloc() and friends must be
>>>>> suitably aligned for assignment to any pointer type, regardless
>>>>> of the size of the request (including zero if the implementation
>>>>> returns a non-null value in such cases).
>>>>
>>>> Many (most) implementation don't have issues with putting mis-ligned
>>>> values into pointers (that is normally only an issue with machines
>>>> where the native pointer is a 'word pointer', not a byte pointer).
>>>>
>>>> The address returned needs to be able to be put into any pointer
>>>> type, but since there is no way to actually put a larger object into
>>>> the malloced memory, there is no way to actually dereference the
>>>> pointer, so the address doesn't need to be aligned well enough to
>>>> actually store/dereference types too big for the allocation.
>>>>
>>>> This does depend on implementation dependent behavior, so the
>>>> implementation can only do this if it 'works' for everything the
>>>> Standard requires. A USER defined equivalent would need some extra
>>>> promises from the implementation beyond what the standard provides
>>>> to do this, but the implementation can just know that it works.
>>>
>>> What I think you're saying, in effect, is that an implementation
>>> can take advantage of undefined behavior so that we can't tell
>>> that what it's doing makes it non-conforming. Probably that's
>>> right, given a sufficiently determined implementation.
>>>
>>> On the other hand, the implementations you're talking about that
>>> allow assignment (but not dereference) of unaligned pointers very
>>> likely also have defined what happens in pointer-to-integer
>>> conversions (which is implementation-defined) in such a way that
>>> we can tell by converting the pointer to an appropriate integer
>>> type and looking at the value in that type. In short, converting
>>> to an integer would let us see that a funny malloc() return value
>>> makes the implementation non-conforming. In practice I believe
>>> it's hard to hide the non-conformingness, because converting to
>>> an integer type exposes the converted pointer's alignedness (in
>>> most implementations), and the rule for converting to an integer
>>> type is implementation-defined, which always lets us discover
>>> what it is.
>>
>> The specification says:
>>
>> 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).
>>
>> Note, it says assigned to a pointer with a fundamental alignment
>> requirement, and used to access such an object. It does NOT say the
>> value itself needs to be fundamentally aligned.
>>
>> If you machine has a fundamental alignment requirement of 8 (for say
>> double), and you allocate 4 bytes of memory and get a results that
>> is only 4 byte aligned, assigning that value to a double* generally
>> is a safe action. The failure to be able to access the value by
>> dereferencing should cause a non-conformity as it is undefined
>> behavior already as the space can NOT point to a double value, since
>> it is too small.
>>
>> Unless you are contending that malloc(1) is required to return a
>> memory space big enough to hold any object of fundamental alignment
>> (which can include user defined structures), the smaller space seems
>> to give the implementation an out.
>
> I think the issue here is that the key phrase ("is suitably
> aligned so that it may be assigned to a pointer to any type of
> object" [not counting those with extended alignments]) may be
> read in more than one way. Reading one: is aligned so that any
> such conversion satisfies the requirements for defined behavior.
> Reading two: is sufficiently aligned so that the assignment
> won't "blow up" in actual execution. (I'm ignoring the matter of
> access, which doesn't bear on my comments. Also, looking back at
> your comments suggests a possible third reading, about which more
> further on.)
>
> The two readings correspond to different points of view, namely,
> the abstract machine in the first case and the actual machine in
> the second case. Note that the distinction is not just an as-if
> scenario. There are significant differences in what is required
> under the two different points of view. (As it turns out I wrote
> a little bit of code recently that depends on the first reading,
> which is what I assume was intended.)
>
> Getting back to your earlier comment, you say "the implementation
> can only do this if it 'works' for everything the Standard
> requires." I think (but am not sure) what you mean by this is
> you assume the first (abstract machine) reading, but propose that
> certain possibilities are allowed under the "as if" rule. Is
> that a fair statement of what you're saying? Or do you mean some
> other reading, not the same as any of the ones I have described?
>
> I don't know if I agree that returning not-fully-aligned pointer
> values (ie, that aren't "really aligned" but act like they are)
> does indeed satisfy what the Standard requires. For the sake of
> discussion though let me agree for the moment. Even if that's
> true, in most implementations whether a pointer value is "really
> aligned" can leak out through converting the pointer value to a
> suitable integer type. For example, in an implementation where
> there is a flat, linear address space, with character addressing,
> and pointer-to-integer conversion just copies the bits, it's very
> easy to tell if a pointer value is appropriately aligned for a
> particular type. The example fits many if not most of the
> implementations you refer to above (ie, those that don't have
> issues putting mis-aligned values into pointers). So an
> implementation would need to be very restricted to be able to
> operate in the manner you suggest (assuming I understand how you
> are reading the key phrase, which I might not). I don't know
> of any implementation that qualifies. Can you suggest one?
>
> Recapping: I assume reading one is what was intended, and that
> was my (assumed) position for earlier comments. I think reading
> two is not what was intended, and allows all sorts of shenanigans,
> but it does allow the "mis-aligned" behavior you proposed. I
> think your position is reading one under an-if scenario, but I'm
> not sure if that's right. So if none of these adequately captures
> your views, I hope you will respond and explain them further.
>
Simple counter example that in my mind says it CAN'T mean that you can
assigned the value to a pointer and succesfully access such a value:
#include <stdlib.h>
struct foo {
unsigned char bar[10000];
};
int foosum(stuct foo fooinst) {
int i;
int sum = 0;
for(i = 0; i < 10000; i++) {
sum += fooinst.bar[i];
}
return sum;
}
int main(void) {
struct foo* foop;
foop = malloc(1);
int sum = foosum(*foop);
return (sum == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
(untested, but should give the general idea.)
By my logic, the call to foosum is allowed to fail and causes undefined
behavior because the memory allocated wasn't big enough. The assignment
of the return from malloc to foop can not cause undefined behavior, even
on a machine with strange alignment restrictions, because of the
requirement to be able to assign to a pointer which needs fundamental
alignment.
The clause to be able to access the object has been overridden by the
fact that we did not ask for enough memory to hold that object, so
therefore we do not need to pad the allocation to be big enough to hold
any object, but only any object that could fit within the allocation,
and thus the value must be suitably aligned for all such objects.
Note that I never said that the implementation somehow 'pretends' that
this lesser aligned pointer is suitably aligned for a bigger object, in
part because the standard never says that it needs to. The value needs
to be able to be put into a pointer to a type that has fundamental
alignment, (and then back if needed to a pointer to a type that is
usable for the memory space) successfully,
I will also point out that even if the implementation defines that
uintptr_t return the direct bitvalue of a flat memory space pointer, I
see nothing in the Standard that actually defines that a fundamentally
aligned pointer value must be a multiple of _Alignof(max_align_t). (and
even if it did, there is still no requirement that the value returned by
malloc actually have that property).
My comment about the implementation being able to depend on
implementation behavior deals with the fact that, in general, putting a
lessor aligned value into a pointer for a more aligned type is undefined
behavior, but if the implementation knows that this operation 'works',
it is allowed to depend on that behavior. Undefined Behavior, and its
consequences is only a matter for user/programmer actions, the
implementation has the overriding 'as if' rule to shield it.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2018-12-05 04:14 -0800 |
| Message-ID | <kfnmupkuq5l.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #138417 |
Richard Damon <Richard@Damon-Family.org> writes:
> On 11/29/18 12:55 PM, Tim Rentsch wrote:
>
>> Richard Damon <Richard@Damon-Family.org> writes:
>>
>>> On 11/24/18 3:32 AM, Tim Rentsch wrote:
>>>
>>>> Richard Damon <Richard@Damon-Family.org> writes:
>>>>
>>>>> On 11/23/18 9:27 PM, Tim Rentsch wrote:
>>>>>
>>>>>> Richard Damon <Richard@Damon-Family.org> writes:
>>>>>>
>>>>>>> In general, malloc and family will return pointers that are
>>>>>>> aligned to the most strict alignment required by the system.
>>>>>>> While it is possible that it could give less strict alignment
>>>>>>> for small allocations, [...]
>>>>>>
>>>>>> My understanding is that such an implementation would not be
>>>>>> conforming. Return values from malloc() and friends must be
>>>>>> suitably aligned for assignment to any pointer type, regardless
>>>>>> of the size of the request (including zero if the implementation
>>>>>> returns a non-null value in such cases).
>>>>>
>>>>> Many (most) implementation don't have issues with putting mis-ligned
>>>>> values into pointers (that is normally only an issue with machines
>>>>> where the native pointer is a 'word pointer', not a byte pointer).
>>>>>
>>>>> The address returned needs to be able to be put into any pointer
>>>>> type, but since there is no way to actually put a larger object into
>>>>> the malloced memory, there is no way to actually dereference the
>>>>> pointer, so the address doesn't need to be aligned well enough to
>>>>> actually store/dereference types too big for the allocation.
>>>>>
>>>>> This does depend on implementation dependent behavior, so the
>>>>> implementation can only do this if it 'works' for everything the
>>>>> Standard requires. A USER defined equivalent would need some extra
>>>>> promises from the implementation beyond what the standard provides
>>>>> to do this, but the implementation can just know that it works.
>>>>
>>>> What I think you're saying, in effect, is that an implementation
>>>> can take advantage of undefined behavior so that we can't tell
>>>> that what it's doing makes it non-conforming. Probably that's
>>>> right, given a sufficiently determined implementation.
>>>>
>>>> On the other hand, the implementations you're talking about that
>>>> allow assignment (but not dereference) of unaligned pointers very
>>>> likely also have defined what happens in pointer-to-integer
>>>> conversions (which is implementation-defined) in such a way that
>>>> we can tell by converting the pointer to an appropriate integer
>>>> type and looking at the value in that type. In short, converting
>>>> to an integer would let us see that a funny malloc() return value
>>>> makes the implementation non-conforming. In practice I believe
>>>> it's hard to hide the non-conformingness, because converting to
>>>> an integer type exposes the converted pointer's alignedness (in
>>>> most implementations), and the rule for converting to an integer
>>>> type is implementation-defined, which always lets us discover
>>>> what it is.
>>>
>>> The specification says:
>>>
>>> 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).
>>>
>>> Note, it says assigned to a pointer with a fundamental alignment
>>> requirement, and used to access such an object. It does NOT say the
>>> value itself needs to be fundamentally aligned.
>>>
>>> If you machine has a fundamental alignment requirement of 8 (for say
>>> double), and you allocate 4 bytes of memory and get a results that
>>> is only 4 byte aligned, assigning that value to a double* generally
>>> is a safe action. The failure to be able to access the value by
>>> dereferencing should cause a non-conformity as it is undefined
>>> behavior already as the space can NOT point to a double value, since
>>> it is too small.
>>>
>>> Unless you are contending that malloc(1) is required to return a
>>> memory space big enough to hold any object of fundamental alignment
>>> (which can include user defined structures), the smaller space seems
>>> to give the implementation an out.
>>
>> I think the issue here is that the key phrase ("is suitably
>> aligned so that it may be assigned to a pointer to any type of
>> object" [not counting those with extended alignments]) may be
>> read in more than one way. Reading one: is aligned so that any
>> such conversion satisfies the requirements for defined behavior.
>> Reading two: is sufficiently aligned so that the assignment
>> won't "blow up" in actual execution. (I'm ignoring the matter of
>> access, which doesn't bear on my comments. Also, looking back at
>> your comments suggests a possible third reading, about which more
>> further on.)
>>
>> The two readings correspond to different points of view, namely,
>> the abstract machine in the first case and the actual machine in
>> the second case. Note that the distinction is not just an as-if
>> scenario. There are significant differences in what is required
>> under the two different points of view. (As it turns out I wrote
>> a little bit of code recently that depends on the first reading,
>> which is what I assume was intended.)
>>
>> Getting back to your earlier comment, you say "the implementation
>> can only do this if it 'works' for everything the Standard
>> requires." I think (but am not sure) what you mean by this is
>> you assume the first (abstract machine) reading, but propose that
>> certain possibilities are allowed under the "as if" rule. Is
>> that a fair statement of what you're saying? Or do you mean some
>> other reading, not the same as any of the ones I have described?
>>
>> I don't know if I agree that returning not-fully-aligned pointer
>> values (ie, that aren't "really aligned" but act like they are)
>> does indeed satisfy what the Standard requires. For the sake of
>> discussion though let me agree for the moment. Even if that's
>> true, in most implementations whether a pointer value is "really
>> aligned" can leak out through converting the pointer value to a
>> suitable integer type. For example, in an implementation where
>> there is a flat, linear address space, with character addressing,
>> and pointer-to-integer conversion just copies the bits, it's very
>> easy to tell if a pointer value is appropriately aligned for a
>> particular type. The example fits many if not most of the
>> implementations you refer to above (ie, those that don't have
>> issues putting mis-aligned values into pointers). So an
>> implementation would need to be very restricted to be able to
>> operate in the manner you suggest (assuming I understand how you
>> are reading the key phrase, which I might not). I don't know
>> of any implementation that qualifies. Can you suggest one?
>>
>> Recapping: I assume reading one is what was intended, and that
>> was my (assumed) position for earlier comments. I think reading
>> two is not what was intended, and allows all sorts of shenanigans,
>> but it does allow the "mis-aligned" behavior you proposed. I
>> think your position is reading one under an-if scenario, but I'm
>> not sure if that's right. So if none of these adequately captures
>> your views, I hope you will respond and explain them further.
>
> Simple counter example that in my mind says it CAN'T mean that you
> can assigned the value to a pointer and succesfully access such a
> value: [...]
I don't know why you bring this up since I have already
acknowledged that access has no bearing on the question.
I take it as given that there may be no access, or even
any hint of access, past the number of bytes actually
requested.
> Note that I never said that the implementation somehow 'pretends'
> that this lesser aligned pointer is suitably aligned for a bigger
> object, in part because the standard never says that it needs to.
> The value needs to be able to be put into a pointer to a type that
> has fundamental alignment, (and then back if needed to a pointer
> to a type that is usable for the memory space) successfully,
You are glossing over the very question I identified as the
primary issue. In short, begging the question.
> I will also point out that even if the implementation defines that
> uintptr_t return the direct bitvalue of a flat memory space
> pointer, I see nothing in the Standard that actually defines that
> a fundamentally aligned pointer value must be a multiple of
> _Alignof(max_align_t). [...]
Alignment can be determined because both the encoding of a
pointer and the mapping to an integer type are implementation
defined.
> My comment about the implementation being able to depend on
> implementation behavior deals with the fact that, in general,
> putting a lessor aligned value into a pointer for a more aligned
> type is undefined behavior, but if the implementation knows that
> this operation 'works', it is allowed to depend on that behavior.
> [...]
Again, begging the question. From you I was expecting better.
[toc] | [prev] | [next] | [standalone]
| From | Richard Damon <Richard@Damon-Family.org> |
|---|---|
| Date | 2018-12-05 08:14 -0500 |
| Message-ID | <NaQND.191644$Ol2.69953@fx17.iad> |
| In reply to | #138527 |
On 12/5/18 7:14 AM, Tim Rentsch wrote:
> Richard Damon <Richard@Damon-Family.org> writes:
>
>> On 11/29/18 12:55 PM, Tim Rentsch wrote:
>>
>>> Richard Damon <Richard@Damon-Family.org> writes:
>>>
>>>> On 11/24/18 3:32 AM, Tim Rentsch wrote:
>>>>
>>>>> Richard Damon <Richard@Damon-Family.org> writes:
>>>>>
>>>>>> On 11/23/18 9:27 PM, Tim Rentsch wrote:
>>>>>>
>>>>>>> Richard Damon <Richard@Damon-Family.org> writes:
>>>>>>>
>>>>>>>> In general, malloc and family will return pointers that are
>>>>>>>> aligned to the most strict alignment required by the system.
>>>>>>>> While it is possible that it could give less strict alignment
>>>>>>>> for small allocations, [...]
>>>>>>>
>>>>>>> My understanding is that such an implementation would not be
>>>>>>> conforming. Return values from malloc() and friends must be
>>>>>>> suitably aligned for assignment to any pointer type, regardless
>>>>>>> of the size of the request (including zero if the implementation
>>>>>>> returns a non-null value in such cases).
>>>>>>
>>>>>> Many (most) implementation don't have issues with putting mis-ligned
>>>>>> values into pointers (that is normally only an issue with machines
>>>>>> where the native pointer is a 'word pointer', not a byte pointer).
>>>>>>
>>>>>> The address returned needs to be able to be put into any pointer
>>>>>> type, but since there is no way to actually put a larger object into
>>>>>> the malloced memory, there is no way to actually dereference the
>>>>>> pointer, so the address doesn't need to be aligned well enough to
>>>>>> actually store/dereference types too big for the allocation.
>>>>>>
>>>>>> This does depend on implementation dependent behavior, so the
>>>>>> implementation can only do this if it 'works' for everything the
>>>>>> Standard requires. A USER defined equivalent would need some extra
>>>>>> promises from the implementation beyond what the standard provides
>>>>>> to do this, but the implementation can just know that it works.
>>>>>
>>>>> What I think you're saying, in effect, is that an implementation
>>>>> can take advantage of undefined behavior so that we can't tell
>>>>> that what it's doing makes it non-conforming. Probably that's
>>>>> right, given a sufficiently determined implementation.
>>>>>
>>>>> On the other hand, the implementations you're talking about that
>>>>> allow assignment (but not dereference) of unaligned pointers very
>>>>> likely also have defined what happens in pointer-to-integer
>>>>> conversions (which is implementation-defined) in such a way that
>>>>> we can tell by converting the pointer to an appropriate integer
>>>>> type and looking at the value in that type. In short, converting
>>>>> to an integer would let us see that a funny malloc() return value
>>>>> makes the implementation non-conforming. In practice I believe
>>>>> it's hard to hide the non-conformingness, because converting to
>>>>> an integer type exposes the converted pointer's alignedness (in
>>>>> most implementations), and the rule for converting to an integer
>>>>> type is implementation-defined, which always lets us discover
>>>>> what it is.
>>>>
>>>> The specification says:
>>>>
>>>> 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).
>>>>
>>>> Note, it says assigned to a pointer with a fundamental alignment
>>>> requirement, and used to access such an object. It does NOT say the
>>>> value itself needs to be fundamentally aligned.
>>>>
>>>> If you machine has a fundamental alignment requirement of 8 (for say
>>>> double), and you allocate 4 bytes of memory and get a results that
>>>> is only 4 byte aligned, assigning that value to a double* generally
>>>> is a safe action. The failure to be able to access the value by
>>>> dereferencing should cause a non-conformity as it is undefined
>>>> behavior already as the space can NOT point to a double value, since
>>>> it is too small.
>>>>
>>>> Unless you are contending that malloc(1) is required to return a
>>>> memory space big enough to hold any object of fundamental alignment
>>>> (which can include user defined structures), the smaller space seems
>>>> to give the implementation an out.
>>>
>>> I think the issue here is that the key phrase ("is suitably
>>> aligned so that it may be assigned to a pointer to any type of
>>> object" [not counting those with extended alignments]) may be
>>> read in more than one way. Reading one: is aligned so that any
>>> such conversion satisfies the requirements for defined behavior.
>>> Reading two: is sufficiently aligned so that the assignment
>>> won't "blow up" in actual execution. (I'm ignoring the matter of
>>> access, which doesn't bear on my comments. Also, looking back at
>>> your comments suggests a possible third reading, about which more
>>> further on.)
>>>
>>> The two readings correspond to different points of view, namely,
>>> the abstract machine in the first case and the actual machine in
>>> the second case. Note that the distinction is not just an as-if
>>> scenario. There are significant differences in what is required
>>> under the two different points of view. (As it turns out I wrote
>>> a little bit of code recently that depends on the first reading,
>>> which is what I assume was intended.)
>>>
>>> Getting back to your earlier comment, you say "the implementation
>>> can only do this if it 'works' for everything the Standard
>>> requires." I think (but am not sure) what you mean by this is
>>> you assume the first (abstract machine) reading, but propose that
>>> certain possibilities are allowed under the "as if" rule. Is
>>> that a fair statement of what you're saying? Or do you mean some
>>> other reading, not the same as any of the ones I have described?
>>>
>>> I don't know if I agree that returning not-fully-aligned pointer
>>> values (ie, that aren't "really aligned" but act like they are)
>>> does indeed satisfy what the Standard requires. For the sake of
>>> discussion though let me agree for the moment. Even if that's
>>> true, in most implementations whether a pointer value is "really
>>> aligned" can leak out through converting the pointer value to a
>>> suitable integer type. For example, in an implementation where
>>> there is a flat, linear address space, with character addressing,
>>> and pointer-to-integer conversion just copies the bits, it's very
>>> easy to tell if a pointer value is appropriately aligned for a
>>> particular type. The example fits many if not most of the
>>> implementations you refer to above (ie, those that don't have
>>> issues putting mis-aligned values into pointers). So an
>>> implementation would need to be very restricted to be able to
>>> operate in the manner you suggest (assuming I understand how you
>>> are reading the key phrase, which I might not). I don't know
>>> of any implementation that qualifies. Can you suggest one?
>>>
>>> Recapping: I assume reading one is what was intended, and that
>>> was my (assumed) position for earlier comments. I think reading
>>> two is not what was intended, and allows all sorts of shenanigans,
>>> but it does allow the "mis-aligned" behavior you proposed. I
>>> think your position is reading one under an-if scenario, but I'm
>>> not sure if that's right. So if none of these adequately captures
>>> your views, I hope you will respond and explain them further.
>>
>> Simple counter example that in my mind says it CAN'T mean that you
>> can assigned the value to a pointer and succesfully access such a
>> value: [...]
>
> I don't know why you bring this up since I have already
> acknowledged that access has no bearing on the question.
> I take it as given that there may be no access, or even
> any hint of access, past the number of bytes actually
> requested.
>
>> Note that I never said that the implementation somehow 'pretends'
>> that this lesser aligned pointer is suitably aligned for a bigger
>> object, in part because the standard never says that it needs to.
>> The value needs to be able to be put into a pointer to a type that
>> has fundamental alignment, (and then back if needed to a pointer
>> to a type that is usable for the memory space) successfully,
>
> You are glossing over the very question I identified as the
> primary issue. In short, begging the question.
>
>> I will also point out that even if the implementation defines that
>> uintptr_t return the direct bitvalue of a flat memory space
>> pointer, I see nothing in the Standard that actually defines that
>> a fundamentally aligned pointer value must be a multiple of
>> _Alignof(max_align_t). [...]
>
> Alignment can be determined because both the encoding of a
> pointer and the mapping to an integer type are implementation
> defined.
>
>> My comment about the implementation being able to depend on
>> implementation behavior deals with the fact that, in general,
>> putting a lessor aligned value into a pointer for a more aligned
>> type is undefined behavior, but if the implementation knows that
>> this operation 'works', it is allowed to depend on that behavior.
>> [...]
>
> Again, begging the question. From you I was expecting better.
>
I could say a lot of the same about your comment.
Where in the Standard does is actually say that the return value of
malloc and family is ACTUALLY fully fundamentally aligned? The wording
is that the value can be assigned to a pointer for a fundamentally
aligned type (which might well accept misaligned values and still 'work'
until you try to access the object through it).
I am also not sure that there is actually any method to check that which
is fully defined by the Standard. The conversion of a pointer to
uintptr_t is Implementation defined, and even with a simple definition
of it, I am not convinced that doing arithmetic on that value has any
defined behavior (with respect to pointer values) unless explicitly
granted by the Implementation.
Can you quote any wording in the Standard that contradicts these statements?
I Quoted what the Standard says about the return value of malloc, and it
does NOT say that the value is fundamentally aligned, only that it can
be put into a pointer with fundamental alignment.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2018-12-05 05:29 -0800 |
| Message-ID | <740cf712-542d-47c1-9682-ec2706e29f56@googlegroups.com> |
| In reply to | #138530 |
On Wednesday, December 5, 2018 at 1:14:31 PM UTC, Richard Damon wrote:
> On 12/5/18 7:14 AM, Tim Rentsch wrote:
> > Richard Damon <Richard@Damon-Family.org> writes:
> >
> >> On 11/29/18 12:55 PM, Tim Rentsch wrote:
> >>
> >>> Richard Damon <Richard@Damon-Family.org> writes:
> >>>
> >>>> On 11/24/18 3:32 AM, Tim Rentsch wrote:
> >>>>
> >>>>> Richard Damon <Richard@Damon-Family.org> writes:
> >>>>>
> >>>>>> On 11/23/18 9:27 PM, Tim Rentsch wrote:
> >>>>>>
> >>>>>>> Richard Damon <Richard@Damon-Family.org> writes:
> >>>>>>>
> >>>>>>>> In general, malloc and family will return pointers that are
> >>>>>>>> aligned to the most strict alignment required by the system.
> >>>>>>>> While it is possible that it could give less strict alignment
> >>>>>>>> for small allocations, [...]
> >>>>>>>
> >>>>>>> My understanding is that such an implementation would not be
> >>>>>>> conforming. Return values from malloc() and friends must be
> >>>>>>> suitably aligned for assignment to any pointer type, regardless
> >>>>>>> of the size of the request (including zero if the implementation
> >>>>>>> returns a non-null value in such cases).
> >>>>>>
> >>>>>> Many (most) implementation don't have issues with putting mis-ligned
> >>>>>> values into pointers (that is normally only an issue with machines
> >>>>>> where the native pointer is a 'word pointer', not a byte pointer).
> >>>>>>
> >>>>>> The address returned needs to be able to be put into any pointer
> >>>>>> type, but since there is no way to actually put a larger object into
> >>>>>> the malloced memory, there is no way to actually dereference the
> >>>>>> pointer, so the address doesn't need to be aligned well enough to
> >>>>>> actually store/dereference types too big for the allocation.
> >>>>>>
> >>>>>> This does depend on implementation dependent behavior, so the
> >>>>>> implementation can only do this if it 'works' for everything the
> >>>>>> Standard requires. A USER defined equivalent would need some extra
> >>>>>> promises from the implementation beyond what the standard provides
> >>>>>> to do this, but the implementation can just know that it works.
> >>>>>
> >>>>> What I think you're saying, in effect, is that an implementation
> >>>>> can take advantage of undefined behavior so that we can't tell
> >>>>> that what it's doing makes it non-conforming. Probably that's
> >>>>> right, given a sufficiently determined implementation.
> >>>>>
> >>>>> On the other hand, the implementations you're talking about that
> >>>>> allow assignment (but not dereference) of unaligned pointers very
> >>>>> likely also have defined what happens in pointer-to-integer
> >>>>> conversions (which is implementation-defined) in such a way that
> >>>>> we can tell by converting the pointer to an appropriate integer
> >>>>> type and looking at the value in that type. In short, converting
> >>>>> to an integer would let us see that a funny malloc() return value
> >>>>> makes the implementation non-conforming. In practice I believe
> >>>>> it's hard to hide the non-conformingness, because converting to
> >>>>> an integer type exposes the converted pointer's alignedness (in
> >>>>> most implementations), and the rule for converting to an integer
> >>>>> type is implementation-defined, which always lets us discover
> >>>>> what it is.
> >>>>
> >>>> The specification says:
> >>>>
> >>>> 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).
> >>>>
> >>>> Note, it says assigned to a pointer with a fundamental alignment
> >>>> requirement, and used to access such an object. It does NOT say the
> >>>> value itself needs to be fundamentally aligned.
> >>>>
> >>>> If you machine has a fundamental alignment requirement of 8 (for say
> >>>> double), and you allocate 4 bytes of memory and get a results that
> >>>> is only 4 byte aligned, assigning that value to a double* generally
> >>>> is a safe action. The failure to be able to access the value by
> >>>> dereferencing should cause a non-conformity as it is undefined
> >>>> behavior already as the space can NOT point to a double value, since
> >>>> it is too small.
> >>>>
> >>>> Unless you are contending that malloc(1) is required to return a
> >>>> memory space big enough to hold any object of fundamental alignment
> >>>> (which can include user defined structures), the smaller space seems
> >>>> to give the implementation an out.
> >>>
> >>> I think the issue here is that the key phrase ("is suitably
> >>> aligned so that it may be assigned to a pointer to any type of
> >>> object" [not counting those with extended alignments]) may be
> >>> read in more than one way. Reading one: is aligned so that any
> >>> such conversion satisfies the requirements for defined behavior.
> >>> Reading two: is sufficiently aligned so that the assignment
> >>> won't "blow up" in actual execution. (I'm ignoring the matter of
> >>> access, which doesn't bear on my comments. Also, looking back at
> >>> your comments suggests a possible third reading, about which more
> >>> further on.)
> >>>
> >>> The two readings correspond to different points of view, namely,
> >>> the abstract machine in the first case and the actual machine in
> >>> the second case. Note that the distinction is not just an as-if
> >>> scenario. There are significant differences in what is required
> >>> under the two different points of view. (As it turns out I wrote
> >>> a little bit of code recently that depends on the first reading,
> >>> which is what I assume was intended.)
> >>>
> >>> Getting back to your earlier comment, you say "the implementation
> >>> can only do this if it 'works' for everything the Standard
> >>> requires." I think (but am not sure) what you mean by this is
> >>> you assume the first (abstract machine) reading, but propose that
> >>> certain possibilities are allowed under the "as if" rule. Is
> >>> that a fair statement of what you're saying? Or do you mean some
> >>> other reading, not the same as any of the ones I have described?
> >>>
> >>> I don't know if I agree that returning not-fully-aligned pointer
> >>> values (ie, that aren't "really aligned" but act like they are)
> >>> does indeed satisfy what the Standard requires. For the sake of
> >>> discussion though let me agree for the moment. Even if that's
> >>> true, in most implementations whether a pointer value is "really
> >>> aligned" can leak out through converting the pointer value to a
> >>> suitable integer type. For example, in an implementation where
> >>> there is a flat, linear address space, with character addressing,
> >>> and pointer-to-integer conversion just copies the bits, it's very
> >>> easy to tell if a pointer value is appropriately aligned for a
> >>> particular type. The example fits many if not most of the
> >>> implementations you refer to above (ie, those that don't have
> >>> issues putting mis-aligned values into pointers). So an
> >>> implementation would need to be very restricted to be able to
> >>> operate in the manner you suggest (assuming I understand how you
> >>> are reading the key phrase, which I might not). I don't know
> >>> of any implementation that qualifies. Can you suggest one?
> >>>
> >>> Recapping: I assume reading one is what was intended, and that
> >>> was my (assumed) position for earlier comments. I think reading
> >>> two is not what was intended, and allows all sorts of shenanigans,
> >>> but it does allow the "mis-aligned" behavior you proposed. I
> >>> think your position is reading one under an-if scenario, but I'm
> >>> not sure if that's right. So if none of these adequately captures
> >>> your views, I hope you will respond and explain them further.
> >>
> >> Simple counter example that in my mind says it CAN'T mean that you
> >> can assigned the value to a pointer and succesfully access such a
> >> value: [...]
> >
> > I don't know why you bring this up since I have already
> > acknowledged that access has no bearing on the question.
> > I take it as given that there may be no access, or even
> > any hint of access, past the number of bytes actually
> > requested.
> >
> >> Note that I never said that the implementation somehow 'pretends'
> >> that this lesser aligned pointer is suitably aligned for a bigger
> >> object, in part because the standard never says that it needs to.
> >> The value needs to be able to be put into a pointer to a type that
> >> has fundamental alignment, (and then back if needed to a pointer
> >> to a type that is usable for the memory space) successfully,
> >
> > You are glossing over the very question I identified as the
> > primary issue. In short, begging the question.
> >
> >> I will also point out that even if the implementation defines that
> >> uintptr_t return the direct bitvalue of a flat memory space
> >> pointer, I see nothing in the Standard that actually defines that
> >> a fundamentally aligned pointer value must be a multiple of
> >> _Alignof(max_align_t). [...]
> >
> > Alignment can be determined because both the encoding of a
> > pointer and the mapping to an integer type are implementation
> > defined.
> >
> >> My comment about the implementation being able to depend on
> >> implementation behavior deals with the fact that, in general,
> >> putting a lessor aligned value into a pointer for a more aligned
> >> type is undefined behavior, but if the implementation knows that
> >> this operation 'works', it is allowed to depend on that behavior.
> >> [...]
> >
> > Again, begging the question. From you I was expecting better.
> >
>
> I could say a lot of the same about your comment.
>
> Where in the Standard does is actually say that the return value of
> malloc and family is ACTUALLY fully fundamentally aligned? The wording
> is that the value can be assigned to a pointer for a fundamentally
> aligned type (which might well accept misaligned values and still 'work'
> until you try to access the object through it).
>
> I am also not sure that there is actually any method to check that which
> is fully defined by the Standard. The conversion of a pointer to
> uintptr_t is Implementation defined, and even with a simple definition
> of it, I am not convinced that doing arithmetic on that value has any
> defined behavior (with respect to pointer values) unless explicitly
> granted by the Implementation.
>
> Can you quote any wording in the Standard that contradicts these statements?
>
> I Quoted what the Standard says about the return value of malloc, and it
> does NOT say that the value is fundamentally aligned, only that it can
> be put into a pointer with fundamental alignment.
>
I believe uintptr_t must be a typedefed alias of one of unsigned char,
short, int, long or long long. Arithmetic is of course defined on these
types.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2018-12-05 14:44 +0100 |
| Message-ID | <pu8koq$t7$1@dont-email.me> |
| In reply to | #138531 |
On 05/12/18 14:29, Malcolm McLean wrote: > On Wednesday, December 5, 2018 at 1:14:31 PM UTC, Richard Damon wrote: <snip> >> I Quoted what the Standard says about the return value of malloc, and it >> does NOT say that the value is fundamentally aligned, only that it can >> be put into a pointer with fundamental alignment. >> > I believe uintptr_t must be a typedefed alias of one of unsigned char, > short, int, long or long long. Arithmetic is of course defined on these > types. > From 7.20.1.4: """ 7.20.1.4 Integer types capable of holding object pointers The following type designates a signed integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer: intptr_t The following type designates an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer: uintptr_t These types are optional. """ There is no requirement that these types exist - malloc does /not/ return a uintptr_t. Secondly, "uintptr_t" is an "unsigned integer type" - it is not required to be a /standard/ integer type. It could be an extended integer type. (See 6.2.5, "Types".)
[toc] | [prev] | [next] | [standalone]
| From | Richard Damon <Richard@Damon-Family.org> |
|---|---|
| Date | 2018-12-05 21:58 -0500 |
| Message-ID | <ff0OD.473149$uJ2.283826@fx27.iad> |
| In reply to | #138531 |
On 12/5/18 8:29 AM, Malcolm McLean wrote:
> I believe uintptr_t must be a typedefed alias of one of unsigned char,
> short, int, long or long long. Arithmetic is of course defined on these
> types.
But that doesn't mean that you can assume much about the pointer from
the value you get.
Given
char* pc;
uintptr_t i;
then given you do:
i = (uintptr_t) pc;
it does not imply that
i+1 == (uintptr_t)(pc+1)
or that
(i % 4) == 0
has any relationship to pc being a suitable value for a pointer
value that needs to be aligned on a 4 byte boundry.
The conversion gives you a mostly opaque value, that you can convert back.
[toc] | [prev] | [next] | [standalone]
| From | Anton Shepelev <anton.txt@g{oogle}mail.com> |
|---|---|
| Date | 2018-12-05 16:38 +0300 |
| Message-ID | <20181205163844.b37df568c2f2356472f00ba5@g{oogle}mail.com> |
| In reply to | #138530 |
Richard Damon: >Where in the Standard does is actually say that the return >value of malloc and family is ACTUALLY fully fundamentally >aligned? The wording is that the value can be assigned to a >pointer for a fundamentally aligned type (which might well >accept misaligned values and still 'work' until you try to >access the object through it). The standard guarrantees corrrect access: 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 (until the space is explicitly deallocated) I believe that the alignment of a pointer is the alignment of its allocated object (if any). -- () ascii ribbon campaign - against html e-mail /\ http://preview.tinyurl.com/qcy6mjc [archived]
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2018-12-05 14:23 +0000 |
| Message-ID | <YbRND.880423$cL2.486936@fx43.iad> |
| In reply to | #138530 |
Richard Damon <Richard@Damon-Family.org> writes: >On 12/5/18 7:14 AM, Tim Rentsch wrote: >> Richard Damon <Richard@Damon-Family.org> writes: >> >>> On 11/29/18 12:55 PM, Tim Rentsch wrote: >>> > >Where in the Standard does is actually say that the return value of >malloc and family is ACTUALLY fully fundamentally aligned? The wording >is that the value can be assigned to a pointer for a fundamentally >aligned type (which might well accept misaligned values and still 'work' >until you try to access the object through it). Generally this is covered the appropriate processor ABI document, not the C standard.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2018-12-05 14:35 -0800 |
| Message-ID | <lnbm5zlhyt.fsf@kst-u.example.com> |
| In reply to | #138530 |
Richard Damon <Richard@Damon-Family.org> writes:
[...]
> Where in the Standard does is actually say that the return value of
> malloc and family is ACTUALLY fully fundamentally aligned? The wording
> is that the value can be assigned to a pointer for a fundamentally
> aligned type (which might well accept misaligned values and still 'work'
> until you try to access the object through it).
It doesn't. Here's the wording (N1570 7.22.3p1):
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).
> I am also not sure that there is actually any method to check that which
> is fully defined by the Standard. The conversion of a pointer to
> uintptr_t is Implementation defined, and even with a simple definition
> of it, I am not convinced that doing arithmetic on that value has any
> defined behavior (with respect to pointer values) unless explicitly
> granted by the Implementation.
I agree. Of course arithmetic on uintptr_t values is possible, since
it's an unsigned integer type. But for example incrementing a uintptr_t
value has no language-defined meaning for the pointer value from
converting the result.
But it can have an implementation-defined meaning.
> Can you quote any wording in the Standard that contradicts these statements?
>
> I Quoted what the Standard says about the return value of malloc, and it
> does NOT say that the value is fundamentally aligned, only that it can
> be put into a pointer with fundamental alignment.
Agreed.
Consider a concrete example. Assume CHAR_BIT==8, 32-bit int, 64-bit
pointers, 64-bit uintptr_t. Assume all pointer types have the same
representation, essentially an index into a monolithic address space.
The implementation-defined conversion from void* to uintptr_t does not
change the representation. int requires 4-byte alignment. A pointer
with 4-byte alignment will have a binary representation ending in 00.
Integer-to-pointer conversion does not check alignment.
void *ptr = malloc(1);
assert(ptr != NULL);
uintptr_t u = (uintptr_t)ptr;
if (u % 4 == 0) {
puts("aligned");
}
else {
puts("not aligned");
}
int *iptr = (int*)u;
This code depends on implementation-defined behavior, but not on
undefined behavior. Given the implementation-defined characteristics of
the assumed implementation, it detects whether the pointer value is
aligned. If it prints "not aligned", then an attempt to dereference
iptr would have undefined behavior. But I believe that an
implementation in which this code prints "not aligned" could be
conforming.
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
Check. We can assign the pointer to an int* object.
and then used
to access such an object or an array of such objects in the
space allocated (until the space is explicitly deallocated).
We can't use the resulting int* to access an int or int[] object,
but only because we've allocated less than sizeof (int) bytes
of memory. The second clause doesn't apply, because there is no
object or array of such objects to be accessed.
I'm not certain that this is what the authors of the standard intended.
It may be that they intended that malloc() must return an aligned
pointer even if the allocation isn't big enough to hold an object that
would need such alignment. Or they may not have considered such cases.
But my interpretation of the wording is that malloc(1) can legally
return a byte-aligned result, even if int, for example, requires
stricter alignment -- as long as operations other than dereferencing the
result don't misbehave.
(In every implementation I've tried, malloc(1) returns a fully aligned
result. It's probably easier that way, and the advantages of being able
to return unaligned pointers are minor.)
--
Keith Thompson (The_Other_Keith) kst@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2018-12-08 19:28 -0800 |
| Message-ID | <kfny38ztm3w.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #138530 |
Richard Damon <Richard@Damon-Family.org> writes:
> On 12/5/18 7:14 AM, Tim Rentsch wrote:
>> Richard Damon <Richard@Damon-Family.org> writes:
>>> On 11/29/18 12:55 PM, Tim Rentsch wrote:
>>>> Richard Damon <Richard@Damon-Family.org> writes:
>>>>> On 11/24/18 3:32 AM, Tim Rentsch wrote:
>>>>>> Richard Damon <Richard@Damon-Family.org> writes:
>>>>>>> On 11/23/18 9:27 PM, Tim Rentsch wrote:
>>>>>>>> Richard Damon <Richard@Damon-Family.org> writes:
>>>>>>>>
>>>>>>>>> In general, malloc and family will return pointers that are
>>>>>>>>> aligned to the most strict alignment required by the system.
>>>>>>>>> While it is possible that it could give less strict alignment
>>>>>>>>> for small allocations, [...]
>>>>>>>>
>>>>>>>> My understanding is that such an implementation would not be
>>>>>>>> conforming. Return values from malloc() and friends must be
>>>>>>>> suitably aligned for assignment to any pointer type, regardless
>>>>>>>> of the size of the request (including zero if the implementation
>>>>>>>> returns a non-null value in such cases).
>>>>>>>
>>>>>>> Many (most) implementation don't have issues with putting mis-ligned
>>>>>>> values into pointers (that is normally only an issue with machines
>>>>>>> where the native pointer is a 'word pointer', not a byte pointer).
>>>>>>>
>>>>>>> The address returned needs to be able to be put into any pointer
>>>>>>> type, but since there is no way to actually put a larger object into
>>>>>>> the malloced memory, there is no way to actually dereference the
>>>>>>> pointer, so the address doesn't need to be aligned well enough to
>>>>>>> actually store/dereference types too big for the allocation.
>>>>>>>
>>>>>>> This does depend on implementation dependent behavior, so the
>>>>>>> implementation can only do this if it 'works' for everything the
>>>>>>> Standard requires. A USER defined equivalent would need some extra
>>>>>>> promises from the implementation beyond what the standard provides
>>>>>>> to do this, but the implementation can just know that it works.
>>>>>>
>>>>>> What I think you're saying, in effect, is that an implementation
>>>>>> can take advantage of undefined behavior so that we can't tell
>>>>>> that what it's doing makes it non-conforming. Probably that's
>>>>>> right, given a sufficiently determined implementation.
>>>>>>
>>>>>> On the other hand, the implementations you're talking about that
>>>>>> allow assignment (but not dereference) of unaligned pointers very
>>>>>> likely also have defined what happens in pointer-to-integer
>>>>>> conversions (which is implementation-defined) in such a way that
>>>>>> we can tell by converting the pointer to an appropriate integer
>>>>>> type and looking at the value in that type. In short, converting
>>>>>> to an integer would let us see that a funny malloc() return value
>>>>>> makes the implementation non-conforming. In practice I believe
>>>>>> it's hard to hide the non-conformingness, because converting to
>>>>>> an integer type exposes the converted pointer's alignedness (in
>>>>>> most implementations), and the rule for converting to an integer
>>>>>> type is implementation-defined, which always lets us discover
>>>>>> what it is.
>>>>>
>>>>> The specification says:
>>>>>
>>>>> 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).
>>>>>
>>>>> Note, it says assigned to a pointer with a fundamental alignment
>>>>> requirement, and used to access such an object. It does NOT say the
>>>>> value itself needs to be fundamentally aligned.
>>>>>
>>>>> If you machine has a fundamental alignment requirement of 8 (for say
>>>>> double), and you allocate 4 bytes of memory and get a results that
>>>>> is only 4 byte aligned, assigning that value to a double* generally
>>>>> is a safe action. The failure to be able to access the value by
>>>>> dereferencing should cause a non-conformity as it is undefined
>>>>> behavior already as the space can NOT point to a double value, since
>>>>> it is too small.
>>>>>
>>>>> Unless you are contending that malloc(1) is required to return a
>>>>> memory space big enough to hold any object of fundamental alignment
>>>>> (which can include user defined structures), the smaller space seems
>>>>> to give the implementation an out.
>>>>
>>>> I think the issue here is that the key phrase ("is suitably
>>>> aligned so that it may be assigned to a pointer to any type of
>>>> object" [not counting those with extended alignments]) may be
>>>> read in more than one way. Reading one: is aligned so that any
>>>> such conversion satisfies the requirements for defined behavior.
>>>> Reading two: is sufficiently aligned so that the assignment
>>>> won't "blow up" in actual execution. (I'm ignoring the matter of
>>>> access, which doesn't bear on my comments. Also, looking back at
>>>> your comments suggests a possible third reading, about which more
>>>> further on.)
>>>>
>>>> The two readings correspond to different points of view, namely,
>>>> the abstract machine in the first case and the actual machine in
>>>> the second case. Note that the distinction is not just an as-if
>>>> scenario. There are significant differences in what is required
>>>> under the two different points of view. (As it turns out I wrote
>>>> a little bit of code recently that depends on the first reading,
>>>> which is what I assume was intended.)
>>>>
>>>> Getting back to your earlier comment, you say "the implementation
>>>> can only do this if it 'works' for everything the Standard
>>>> requires." I think (but am not sure) what you mean by this is
>>>> you assume the first (abstract machine) reading, but propose that
>>>> certain possibilities are allowed under the "as if" rule. Is
>>>> that a fair statement of what you're saying? Or do you mean some
>>>> other reading, not the same as any of the ones I have described?
>>>>
>>>> I don't know if I agree that returning not-fully-aligned pointer
>>>> values (ie, that aren't "really aligned" but act like they are)
>>>> does indeed satisfy what the Standard requires. For the sake of
>>>> discussion though let me agree for the moment. Even if that's
>>>> true, in most implementations whether a pointer value is "really
>>>> aligned" can leak out through converting the pointer value to a
>>>> suitable integer type. For example, in an implementation where
>>>> there is a flat, linear address space, with character addressing,
>>>> and pointer-to-integer conversion just copies the bits, it's very
>>>> easy to tell if a pointer value is appropriately aligned for a
>>>> particular type. The example fits many if not most of the
>>>> implementations you refer to above (ie, those that don't have
>>>> issues putting mis-aligned values into pointers). So an
>>>> implementation would need to be very restricted to be able to
>>>> operate in the manner you suggest (assuming I understand how you
>>>> are reading the key phrase, which I might not). I don't know
>>>> of any implementation that qualifies. Can you suggest one?
>>>>
>>>> Recapping: I assume reading one is what was intended, and that
>>>> was my (assumed) position for earlier comments. I think reading
>>>> two is not what was intended, and allows all sorts of shenanigans,
>>>> but it does allow the "mis-aligned" behavior you proposed. I
>>>> think your position is reading one under an-if scenario, but I'm
>>>> not sure if that's right. So if none of these adequately captures
>>>> your views, I hope you will respond and explain them further.
>>>
>>> Simple counter example that in my mind says it CAN'T mean that you
>>> can assigned the value to a pointer and succesfully access such a
>>> value: [...]
>>
>> I don't know why you bring this up since I have already
>> acknowledged that access has no bearing on the question.
>> I take it as given that there may be no access, or even
>> any hint of access, past the number of bytes actually
>> requested.
>>
>>> Note that I never said that the implementation somehow 'pretends'
>>> that this lesser aligned pointer is suitably aligned for a bigger
>>> object, in part because the standard never says that it needs to.
>>> The value needs to be able to be put into a pointer to a type that
>>> has fundamental alignment, (and then back if needed to a pointer
>>> to a type that is usable for the memory space) successfully,
>>
>> You are glossing over the very question I identified as the
>> primary issue. In short, begging the question.
>>
>>> I will also point out that even if the implementation defines that
>>> uintptr_t return the direct bitvalue of a flat memory space
>>> pointer, I see nothing in the Standard that actually defines that
>>> a fundamentally aligned pointer value must be a multiple of
>>> _Alignof(max_align_t). [...]
>>
>> Alignment can be determined because both the encoding of a
>> pointer and the mapping to an integer type are implementation
>> defined.
>>
>>> My comment about the implementation being able to depend on
>>> implementation behavior deals with the fact that, in general,
>>> putting a lessor aligned value into a pointer for a more aligned
>>> type is undefined behavior, but if the implementation knows that
>>> this operation 'works', it is allowed to depend on that behavior.
>>> [...]
>>
>> Again, begging the question. From you I was expecting better.
>
> I could say a lot of the same about your comment.
>
> Where in the Standard does is actually say that the return value of
> malloc and family is ACTUALLY fully fundamentally aligned? The wording
> is that the value can be assigned to a pointer for a fundamentally
> aligned type (which might well accept misaligned values and still 'work'
> until you try to access the object through it).
>
> I am also not sure that there is actually any method to check that which
> is fully defined by the Standard. The conversion of a pointer to
> uintptr_t is Implementation defined, and even with a simple definition
> of it, I am not convinced that doing arithmetic on that value has any
> defined behavior (with respect to pointer values) unless explicitly
> granted by the Implementation.
>
> Can you quote any wording in the Standard that contradicts these statements?
>
> I Quoted what the Standard says about the return value of malloc, and it
> does NOT say that the value is fundamentally aligned, only that it can
> be put into a pointer with fundamental alignment.
I was composing a reply when it occurred to me to check the
Defect Reports. DR 75 -
http://www.open-std.org/jtc1/sc22/WG14/www/docs/dr_075.html
addresses the question squarely and plainly. The returned
pointer must be aligned for all types, even for malloc(1).
[toc] | [prev] | [next] | [standalone]
| From | Richard Damon <Richard@Damon-Family.org> |
|---|---|
| Date | 2018-12-09 08:18 -0500 |
| Message-ID | <qC8PD.224612$un2.215412@fx14.iad> |
| In reply to | #138623 |
On 12/8/18 10:28 PM, Tim Rentsch wrote: > Richard Damon <Richard@Damon-Family.org> writes: Where in the Standard does is actually say that the return value of >> malloc and family is ACTUALLY fully fundamentally aligned? The wording >> is that the value can be assigned to a pointer for a fundamentally >> aligned type (which might well accept misaligned values and still 'work' >> until you try to access the object through it). >> >> I am also not sure that there is actually any method to check that which >> is fully defined by the Standard. The conversion of a pointer to >> uintptr_t is Implementation defined, and even with a simple definition >> of it, I am not convinced that doing arithmetic on that value has any >> defined behavior (with respect to pointer values) unless explicitly >> granted by the Implementation. >> >> Can you quote any wording in the Standard that contradicts these statements? >> >> I Quoted what the Standard says about the return value of malloc, and it >> does NOT say that the value is fundamentally aligned, only that it can >> be put into a pointer with fundamental alignment. > > I was composing a reply when it occurred to me to check the > Defect Reports. DR 75 - > > http://www.open-std.org/jtc1/sc22/WG14/www/docs/dr_075.html > > addresses the question squarely and plainly. The returned > pointer must be aligned for all types, even for malloc(1). > Actually, the Question posted doesn't imply or require the explanation given. Yes, the Standard clearly requires that pointer value from malloc needs to be able to round trip through any type of pointer that doesn't require an extended alignment. I would contend that the Standard hasn't defined any terminology to even really define a memory space being suitably aligned for a type too big to put into it. Alignment is defined in terms of being able to access, and you can't access an object bigger than the space available.
[toc] | [prev] | [next] | [standalone]
| From | Richard Damon <Richard@Damon-Family.org> |
|---|---|
| Date | 2018-12-09 14:35 -0500 |
| Message-ID | <z8ePD.224619$un2.14043@fx14.iad> |
| In reply to | #138628 |
On 12/9/18 8:18 AM, Richard Damon wrote: > On 12/8/18 10:28 PM, Tim Rentsch wrote: >> Richard Damon <Richard@Damon-Family.org> writes: > Where in the Standard does is actually say that the return value of >>> malloc and family is ACTUALLY fully fundamentally aligned? The wording >>> is that the value can be assigned to a pointer for a fundamentally >>> aligned type (which might well accept misaligned values and still 'work' >>> until you try to access the object through it). >>> >>> I am also not sure that there is actually any method to check that which >>> is fully defined by the Standard. The conversion of a pointer to >>> uintptr_t is Implementation defined, and even with a simple definition >>> of it, I am not convinced that doing arithmetic on that value has any >>> defined behavior (with respect to pointer values) unless explicitly >>> granted by the Implementation. >>> >>> Can you quote any wording in the Standard that contradicts these statements? >>> >>> I Quoted what the Standard says about the return value of malloc, and it >>> does NOT say that the value is fundamentally aligned, only that it can >>> be put into a pointer with fundamental alignment. >> >> I was composing a reply when it occurred to me to check the >> Defect Reports. DR 75 - >> >> http://www.open-std.org/jtc1/sc22/WG14/www/docs/dr_075.html >> >> addresses the question squarely and plainly. The returned >> pointer must be aligned for all types, even for malloc(1). >> > > Actually, the Question posted doesn't imply or require the explanation > given. Yes, the Standard clearly requires that pointer value from malloc > needs to be able to round trip through any type of pointer that doesn't > require an extended alignment. > > I would contend that the Standard hasn't defined any terminology to even > really define a memory space being suitably aligned for a type too big > to put into it. Alignment is defined in terms of being able to access, > and you can't access an object bigger than the space available. > Thinking about this a bit more, first the DR is to C90, and as I pointed out, the direct question being asked was the about the round tripping of a pointer value. C90 had even less defined about being able to do anything to figure out how aligned a pointer was. The 'off hand' comment that 7.10.3 requiring the memory actually being aligned for /any/ type is first obsolete, as the later standard introduces over-aligned types that need stricter alignment than malloc needs to meet. Also, due to the 'as if' rule, and the Undefined Behavior nature of actually accessing an object bigger than the allocated space, there is no way I can think of for the application to actually detect that the pointer isn't properly aligned using only defined behavior. (Can you? especially using only defined behavor from C90) Note that the normal method of casting the pointer to an integer type and masking bits only works if the implementation very specifically defines that this works.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2018-12-09 14:04 -0800 |
| Message-ID | <ln5zw2jr13.fsf@kst-u.example.com> |
| In reply to | #138630 |
Richard Damon <Richard@Damon-Family.org> writes:
[...]
> Thinking about this a bit more, first the DR is to C90, and as I pointed
> out, the direct question being asked was the about the round tripping of
> a pointer value.
No, the question being asked was about alignment. The sub-question
about round-trip conversion was an example of a consequence of the
answer to the main question. The response addresses both the main
question and the example.
http://www.open-std.org/jtc1/sc22/WG14/www/docs/dr_075.html
Question
Item 12 - alignment of allocated memory
Is a piece of memory allocated by malloc required to be aligned
suitably for any type, or only for those types that will fit into
the space? For example, following the assignment:
void *vp = malloc (1);
is it required that (void *)(int *)vp compare equal to vp (assuming
that sizeof(int) > 1), or is it permissible for vp to be a value not
suitably aligned to point to an int?
Response
Subclause 7.10.3 requires allocated memory to be suitably aligned
for any type, so they must compare equal.
You *could* have an implementation in which a non-null pointer
returned by malloc(1) is not suitably aligned to point to an int,
and yet the round-trip conversion still works -- but the response
says that such an implementation would not be conforming.
> C90 had even less defined about being able to do anything to figure out
> how aligned a pointer was. The 'off hand' comment that 7.10.3 requiring
> the memory actually being aligned for /any/ type is first obsolete, as
> the later standard introduces over-aligned types that need stricter
> alignment than malloc needs to meet.
The DR applies to C90, and there were some changes in the wording
between C90 and C11, but I believe the DR still applies to the
new wording. The pointer still has to be "suitably aligned so
that it may be assigned to a pointer to any type of object *with
a fundamental alignment requirement*", and we can reasonably add
that wording to the DR, but there was no point in going back and
updating it.
> Also, due to the 'as if' rule, and the Undefined Behavior nature of
> actually accessing an object bigger than the allocated space, there is
> no way I can think of for the application to actually detect that the
> pointer isn't properly aligned using only defined behavior. (Can you?
> especially using only defined behavor from C90)
>
> Note that the normal method of casting the pointer to an integer type
> and masking bits only works if the implementation very specifically
> defines that this works.
Yes -- but if an implementation defines that it works, we can still use
it to determine whether the pointer is correctly aligned. We can't
detect whether the result of malloc(1) is suitably aligned using only
language-defined behavior, but we can, *for some implementations*,
detect it using implementation-defined behavior (while avoiding any
undefined behavior).
For an implementation that specifies certain behaviors for pointer
representations and pointer-to-integer conversions, the following
program must not print "malloc(1) is NOT suitably aligned for int*".
For an implementation that doesn't specify those behaviors, it could.
The specific implementation-defined requirements I have in mind are:
- uintptr_t exists
- If a given void* value is N-byte aligned, then converting the value
to uintprt_t yields a value congruent to 0 modulo N.
(I may have missed something.)
(An implementation for which malloc(1) returns a misaligned pointer, but
which doesn't provide any implementation-defined way to determine a
pointer's alignment, could be non-conforming but in a way that is not
possible to detect. Which is why I question the usefulness of the
requirement -- but I accept, given the DR, that it is a requirement.)
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#ifndef UINTPTR_MAX
#error "uintptr_t is not defined"
#endif
int main(void) {
void *p = malloc(1);
if (p == NULL) {
puts("malloc(1) failed");
}
else {
uintptr_t n = (uintptr_t)p;
if (n % _Alignof (int) == 0) {
puts("malloc(1) is suitably aligned for int*");
}
else {
puts("malloc(1) is NOT suitably aligned for int*");
}
}
}
--
Keith Thompson (The_Other_Keith) kst@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Richard Damon <Richard@Damon-Family.org> |
|---|---|
| Date | 2018-12-09 20:40 -0500 |
| Message-ID | <zujPD.818409$MN2.438158@fx02.iad> |
| In reply to | #138631 |
On 12/9/18 5:04 PM, Keith Thompson wrote:
> Richard Damon <Richard@Damon-Family.org> writes:
> [...]
>> Thinking about this a bit more, first the DR is to C90, and as I pointed
>> out, the direct question being asked was the about the round tripping of
>> a pointer value.
>
> No, the question being asked was about alignment. The sub-question
> about round-trip conversion was an example of a consequence of the
> answer to the main question. The response addresses both the main
> question and the example.
>
> http://www.open-std.org/jtc1/sc22/WG14/www/docs/dr_075.html
>
> Question
>
> Item 12 - alignment of allocated memory
> Is a piece of memory allocated by malloc required to be aligned
> suitably for any type, or only for those types that will fit into
> the space? For example, following the assignment:
> void *vp = malloc (1);
> is it required that (void *)(int *)vp compare equal to vp (assuming
> that sizeof(int) > 1), or is it permissible for vp to be a value not
> suitably aligned to point to an int?
>
> Response
>
> Subclause 7.10.3 requires allocated memory to be suitably aligned
> for any type, so they must compare equal.
>
And the example shows the meaning to give to suitably aligned.
The definition of alignment in the Standard, (6.2.8p1)
An alignment is an implementation-defined integer value representing the
number of bytes between successive addresses at which a given object can
be allocated.
Is a phrase with no meaning for a memory space too small to hold even 1
such object. If malloc returns a 4 byte chunk of memory, there is NO
address that is suitable for an 8 byte object as it just doesn't fit.
One restriction on pointers and alignment, is that a pointer need not
hold values not suitably aligned for that type, so one way to possible
conclusively prove that a pointer value is not suitably aligned, is a
round trip test. If a value that is supposed to be suitably aligned is
converted from void* to type* and back to void* and it no longer
compares equal to the original value, then the value must not have been
aligned (the converse is not true, successful round trip does not
indicate necessity of being suitably aligned).
> You *could* have an implementation in which a non-null pointer
> returned by malloc(1) is not suitably aligned to point to an int,
> and yet the round-trip conversion still works -- but the response
> says that such an implementation would not be conforming.
But only if you can detect that with code that doesn't perform Undefined
Behavior, ortherwise the "As If" rule is in effect.
>
>> C90 had even less defined about being able to do anything to figure out
>> how aligned a pointer was. The 'off hand' comment that 7.10.3 requiring
>> the memory actually being aligned for /any/ type is first obsolete, as
>> the later standard introduces over-aligned types that need stricter
>> alignment than malloc needs to meet.
>
> The DR applies to C90, and there were some changes in the wording
> between C90 and C11, but I believe the DR still applies to the
> new wording. The pointer still has to be "suitably aligned so
> that it may be assigned to a pointer to any type of object *with
> a fundamental alignment requirement*", and we can reasonably add
> that wording to the DR, but there was no point in going back and
> updating it.
>
>> Also, due to the 'as if' rule, and the Undefined Behavior nature of
>> actually accessing an object bigger than the allocated space, there is
>> no way I can think of for the application to actually detect that the
>> pointer isn't properly aligned using only defined behavior. (Can you?
>> especially using only defined behavor from C90)
>>
>> Note that the normal method of casting the pointer to an integer type
>> and masking bits only works if the implementation very specifically
>> defines that this works.
>
> Yes -- but if an implementation defines that it works, we can still use
> it to determine whether the pointer is correctly aligned. We can't
> detect whether the result of malloc(1) is suitably aligned using only
> language-defined behavior, but we can, *for some implementations*,
> detect it using implementation-defined behavior (while avoiding any
> undefined behavior).
Yes, SOME implementations may provide enough definition in
Implementation Defined Behavior to prohibit them from this trick, but if
they don't provide those definitions, the program can't legally catch them.
>
> For an implementation that specifies certain behaviors for pointer
> representations and pointer-to-integer conversions, the following
> program must not print "malloc(1) is NOT suitably aligned for int*".
> For an implementation that doesn't specify those behaviors, it could.
>
> The specific implementation-defined requirements I have in mind are:
> - uintptr_t exists
> - If a given void* value is N-byte aligned, then converting the value
> to uintprt_t yields a value congruent to 0 modulo N.
Yes, that is the sort of rule that prohibits the behavior, something
that converts a uintptr_t value of a pointer into an alignment. Without
such a statement
> (I may have missed something.)
>
> (An implementation for which malloc(1) returns a misaligned pointer, but
> which doesn't provide any implementation-defined way to determine a
> pointer's alignment, could be non-conforming but in a way that is not
> possible to detect. Which is why I question the usefulness of the
> requirement -- but I accept, given the DR, that it is a requirement.)
But is it? If no program can detect (observe) the condition, is it
non-conforming? 5.1.2.3p6 says that conformance is based on observable
behavior! (and then defines what is observable behavior)
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <stdint.h>
>
> #ifndef UINTPTR_MAX
> #error "uintptr_t is not defined"
> #endif
>
> int main(void) {
> void *p = malloc(1);
> if (p == NULL) {
> puts("malloc(1) failed");
> }
> else {
> uintptr_t n = (uintptr_t)p;
> if (n % _Alignof (int) == 0) {
> puts("malloc(1) is suitably aligned for int*");
> }
> else {
> puts("malloc(1) is NOT suitably aligned for int*");
> }
> }
> }
>
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2018-12-17 07:18 -0800 |
| Message-ID | <kfnk1k8rxkm.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #138633 |
Richard Damon <Richard@Damon-Family.org> writes: > On 12/9/18 5:04 PM, Keith Thompson wrote: > >> Richard Damon <Richard@Damon-Family.org> writes: [I am taking out some pieces that seem incidental or repetitive] >>> Thinking about this a bit more, first the DR is to C90, and as I >>> pointed out, the direct question being asked was the about the >>> round tripping of a pointer value. >> >> No, the question being asked was about alignment. The sub-question >> about round-trip conversion was an example of a consequence of the >> answer to the main question. The response addresses both the main >> question and the example. >> >> http://www.open-std.org/jtc1/sc22/WG14/www/docs/dr_075.html >> >> Question >> >> Item 12 - alignment of allocated memory >> Is a piece of memory allocated by malloc required to be aligned >> suitably for any type, or only for those types that will fit >> into the space? For example, following the assignment: >> void *vp = malloc (1); >> is it required that (void *)(int *)vp compare equal to vp >> (assuming that sizeof(int) > 1), or is it permissible for vp to >> be a value not suitably aligned to point to an int? >> >> Response >> >> Subclause 7.10.3 requires allocated memory to be suitably >> aligned for any type, so they must compare equal. > > And the example shows the meaning to give to suitably aligned. > > The definition of alignment in the Standard, (6.2.8p1) > > An alignment is an implementation-defined integer value representing > the number of bytes between successive addresses at which a given > object can be allocated. > > Is a phrase with no meaning for a memory space too small to hold > even 1 such object. If malloc returns a 4 byte chunk of memory, > there is NO address that is suitable for an 8 byte object as it > just doesn't fit. > > One restriction on pointers and alignment, is that a pointer need > not hold values not suitably aligned for that type, so one way to > possible conclusively prove that a pointer value is not suitably > aligned, is a round trip test. If a value that is supposed to be > suitably aligned is converted from void* to type* and back to > void* and it no longer compares equal to the original value, then > the value must not have been aligned (the converse is not true, > successful round trip does not indicate necessity of being > suitably aligned). > >> You *could* have an implementation in which a non-null pointer >> returned by malloc(1) is not suitably aligned to point to an int, >> and yet the round-trip conversion still works -- but the response >> says that such an implementation would not be conforming. > > But only if you can detect that with code that doesn't perform > Undefined Behavior, ortherwise the "As If" rule is in effect. I have the sense that we are concerned with somewhat different questions. The question I am trying to answer is What meaning do the authors of the Standard intend? The question (I think) you are trying is answer is What can we deduce purely from the text of the Standard itself (perhaps plus stuff in DR's)? That difference (assuming it is present) would explain some of the difficulty in the discussion. Having said that, let me say a few things that I think are germane under both realms. First, the definition of alignment is not in section 6.2.8 but in section 3.2 (3.1 in C90). The statement in 6.2.8 is a statement about alignment, not its definition. Second, alignment is defined in terms of addresses, which exist independently of whether any pointer value holds them. Third, the addressing structure of the execution environment is fixed. Particular object addresses may change from run to run, but the addressing structure itself stays fixed. Fourth, as a consequence, the alignment of an address doesn't change: what it is in this program run is the same as the last one and the next one, etc. Fifth, therefore, it is always possible to determine whether a pointer value is suitably aligned, by looking at the bits - because the encoding is implementation-defined, we can determine which address the pointer holds, which tells us the alignment. Some of the above depends on statements made in footnotes, as for example the footnote on pointer equality comparisons. Part of the point of having footnotes is to convey context or working assumptions that are hard to define rigorously, which looks like (to me anyway) what is going on here.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2018-12-17 12:35 -0800 |
| Message-ID | <ln7eg7gacy.fsf@kst-u.example.com> |
| In reply to | #138714 |
Tim Rentsch <txr@alumni.caltech.edu> writes:
[...]
> Fifth, therefore, it is always possible to determine whether a
> pointer value is suitably aligned, by looking at the bits -
> because the encoding is implementation-defined, we can determine
> which address the pointer holds, which tells us the alignment.
[...]
Where does the standard say that pointer representation is
implementation-defined?
6.2.6.1p1 says:
The representations of all types are unspecified except as
stated in this subclause.
Pointer types are not mentioned in the remainder of 6.2.6.
(I just noticed what I think is a minor flaw, not relevant to my
question above. The phrase "this subclause" *should* refer to 6.2.6,
but it appears in 6.2.6.1.)
Of course "unspecified" is consistent with "implementation-defined",
but I don't see anything that requires the implementation to
document its pointer representation. (Conversions between pointers
and integers have implementation-defined results, but that doesn't
imply that pointer representation must be documented.)
--
Keith Thompson (The_Other_Keith) kst@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2018-12-17 12:48 -0800 |
| Message-ID | <kfn36qvnale.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #138717 |
Keith Thompson <kst-u@mib.org> writes:
> Tim Rentsch <txr@alumni.caltech.edu> writes:
> [...]
>
>> Fifth, therefore, it is always possible to determine whether a
>> pointer value is suitably aligned, by looking at the bits -
>> because the encoding is implementation-defined, we can determine
>> which address the pointer holds, which tells us the alignment.
>
> [...]
>
> Where does the standard say that pointer representation is
> implementation-defined?
>
> 6.2.6.1p1 says:
> The representations of all types are unspecified except as
> stated in this subclause.
>
> Pointer types are not mentioned in the remainder of 6.2.6.
It's in the very next paragraph, 6.2.6.1p2:
Except for bit-fields, objects are composed of contiguous
sequences of one or more bytes, the number, order, and
encoding of which are either explicitly specified or
implementation-defined.
If we know how a pointer object encodes an address, then knowing
the bits of the pointer should let us know the address.
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <invalid_chris_thomasson@invalid.invalid> |
|---|---|
| Date | 2018-11-24 18:33 -0800 |
| Message-ID | <ptd1lm$cq0$1@dont-email.me> |
| In reply to | #138206 |
On 11/23/2018 6:27 PM, Tim Rentsch wrote:
> Richard Damon <Richard@Damon-Family.org> writes:
>
>> In general, malloc and family will return pointers that are
>> aligned to the most strict alignment required by the system.
>> While it is possible that it could give less strict alignment
>> for small allocations, [...]
>
> My understanding is that such an implementation would not be
> conforming. Return values from malloc() and friends must be
> suitably aligned for assignment to any pointer type, regardless
> of the size of the request (including zero if the implementation
> returns a non-null value in such cases).
>
This is not a malloc, it is a hack. If one uses ralloct to create an
array of a type, it will find the max alignment for said type. malloc
just uses the max alignment no matter what, and everything works.
ralloct can use a smaller value if the type has an alignment less than
the max alignment. max_align_t ?
____________________
double* d = ralloct(®ion, 42, double);
if (d)
{
// d has 42 objects, d is at index 0.
// move d to index 1
d = d + 1;
}
____________________
user defined structures behave the same way.
[toc] | [prev] | [next] | [standalone]
| From | Anton Shepelev <anton.txt@gmail.com> |
|---|---|
| Date | 2018-11-19 02:26 +0300 |
| Subject | My dynamic arrays module [was:Re: Pointer conversion and alignment] |
| Message-ID | <20181119022614.5cf93af72a29cb41cdc86910@gmail.com> |
| In reply to | #138077 |
Below is the second edition of my dynamic arrays module.
My goals are:
1. Transparency (looks like a usual array or pointer).
2. Portability.
3. Compatibility with C89.
4. No macros exposed.
Is it portable? Is there a better way to store and access
the array metadata? For example, will alignment of the
size, capacity, and length fields increase performace?
Notice the new portable interface of the allocation
functions, which now return the new value of the dynamic
array variable. Since error is indicated as a NULL value,
the allocation functions must free the array internally.
What is the best type for the index: int, unsinged int,
size_t?
================================== dynarray.h ==================================
/* `a' is the array, declared as a pointer of the desired type and `data' is
the contents of an array element. The functions returning `void*' return the
new array variable, potentially modified due to reallocation. It is NULL in
case of an error. */
void* da_new ( size_t size ); /* create an empty array */
void da_free ( void * a ); /* free an array */
void* da_setlen( void * a, int len ); /* set the length */
int da_len ( void * a ); /* get the length */
void* da_add ( void * a, void * data ); /* add a new element */
void* da_addemp( void * a, void ** data ); /* add an empty element */
#include <stdlib.h>
#include <string.h>
#include "dynarray.h"
================================== dynarray.c ==================================
Memory layout:
Field: [length][capacity][size ][data...]
Type: int int size_t
*/
/* ------------- Access to int and size_t with strict aliasing -------------- */
union intalias
{ char cdata[sizeof(int)];
int idata;
};
static void setint(void* dest, int val)
{ union intalias ia;
ia.idata = val;
memcpy(dest,ia.cdata, sizeof(int));
}
static int getint(void* source)
{ union intalias ia;
memcpy(&ia, source, sizeof(int));
return ia.idata;
}
union sizealias
{ char cdata[sizeof(size_t)];
size_t sdata;
};
static void setsize(void* dest, size_t val)
{ union sizealias sa;
sa.sdata = val;
memcpy(dest,sa.cdata, sizeof(size_t));
}
static size_t getsize(void* source)
{ union sizealias sa;
memcpy(&sa, source, sizeof(size_t));
return sa.sdata;
}
/* ------------ Macros to access the fields of a dynamic array: ------------- */
#define SHIFT(A,S) (((char*)A) - (S))
#define OFFSET ( sizeof(size_t) + 2*sizeof(int))
#define ORIGIN(A) SHIFT(A, OFFSET)
#define GETLEN(A) getint (ORIGIN(A))
#define GETSIZE(A) getsize(SHIFT((A),sizeof(size_t)))
#define GETCAP(A) getint (SHIFT((A),sizeof(size_t)+sizeof(int)))
#define SETLEN(A,L) setint (ORIGIN(A),(L))
#define SETSIZE(A,S) setsize(SHIFT((A),sizeof(size_t)),S)
#define SETCAP(A,C) setint (SHIFT((A),sizeof(size_t)+sizeof(int)),(C))
/* ------------------------ Memory (re)allocation --------------------------- */
static void* da_alloc( void *a, int cap, size_t size )
{ char *org0, *org1;
if( a == NULL ) org0 = NULL;
else org0 = ORIGIN( a );
org1 = realloc( org0, cap * size + OFFSET);
if( org1 != NULL )
{ a = org1 + OFFSET;
SETCAP(a, cap);
}
else /* must free the array because the user code will have NULL */
{ free( org0 );
a = NULL;
}
return a;
}
/* ------------ Operations on a dynamic array (public functions) ------------ */
void* da_new( size_t size )
{ void* a;
a = da_alloc( NULL, 1, size );
if( a != NULL )
{ SETSIZE(a, size);
SETLEN( a, 0);
}
return a;
}
void* da_setlen( void * a, int len )
{ int newcap;
newcap = 1;
while( newcap < len )
{ newcap = newcap << 1; }
a = da_alloc( a, newcap, GETSIZE(a) );
if( a != NULL ) SETLEN(a, len);
return a;
}
void* da_addemp( void * a, void ** data )
{ int cap, len;
cap = GETCAP(a);
len = GETLEN(a);
if( len == cap )
{ cap = 2 * cap;
a = da_alloc( a, cap, GETSIZE(a) );
if( a == NULL ) goto Error;
}
*data = (char*)a + GETSIZE(a) * len;
SETLEN(a, len + 1);
Error:
return a;
}
void* da_add( void * a, void * data )
{ void * addr;
addr = NULL; /* to avoid a warning that it may be uninitialised */
a = da_addemp( a, &addr );
if( a != NULL ) memcpy( addr, data, GETSIZE(a) );
return a;
}
void da_free( void * a )
{ free( ORIGIN( a ) ); }
int da_len( void * a )
{ return GETLEN( a ); }
================================== da_sample.c =================================
#include <stdio.h>
#include <string.h>
#include "dynarray.h"
int main( int argc, char** argv )
{ int *a, v, i, l, excode;
void* vP;
excode = 1;
a = da_new( sizeof( int ) );
if( a == NULL ) goto ERROR;
a = da_setlen( a, 2 );
if( a == NULL ) goto ERROR;
a[0] = 0;
a[1] = 1;
a = da_setlen( a, 4 );
if( a == NULL ) goto ERROR;
a[2] = 2;
a[3] = 3;
v = 4;
a = da_add( a, &v );
if( a == NULL ) goto ERROR;
v = 5;
a = da_addemp( a, &vP );
if( a == NULL ) goto ERROR;
memcpy( vP, &v, sizeof( int ) );
l = da_len( a );
for( i = 0; i < l; i++ )
{ printf("%i ", a[i]); }
excode = 0;
da_free( a );
ERROR: return excode;
}
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2018-11-19 11:08 +0000 |
| Subject | Re: My dynamic arrays module [was:Re: Pointer conversion and alignment] |
| Message-ID | <87va4tiat8.fsf@bsb.me.uk> |
| In reply to | #138110 |
Anton Shepelev <anton.txt@gmail.com> writes:
> Below is the second edition of my dynamic arrays module.
> My goals are:
>
> 1. Transparency (looks like a usual array or pointer).
> 2. Portability.
> 3. Compatibility with C89.
> 4. No macros exposed.
>
> Is it portable? Is there a better way to store and access
> the array metadata? For example, will alignment of the
> size, capacity, and length fields increase performace?
Only the size element might be a problem -- the others are guaranteed to
be aligned. And below, I argue that all three should be of the same
type anyway and hence they will all be aligned.
Alignment might be an issue for the data, though. From the point of
view of portable access the optimal layout is
+----------+----------+----------+---+--- ------ --+
| length | capacity | size |...| ... data ... |
+----------+----------+----------+---+--- ------ --+
^
| padding
where a possibly zero-sized gap is left after the three equal-sized
meta-data items so as to re-gain maximal alignment. The simplest way to
achieve this in modern C define a struct for the header:
struct meta_data {
int length;
int capacity;
size_t size;
max_align_t data[];
};
Here I've used your types. If any of these need more alignment then
there will be gaps in this structure.
> Notice the new portable interface of the allocation
> functions, which now return the new value of the dynamic
> array variable. Since error is indicated as a NULL value,
> the allocation functions must free the array internally.
>
> What is the best type for the index: int, unsinged int,
> size_t?
I don't see why you've made these different. On many implementations,
size_t is 8 bytes and int is 4, but surely a vast number of small
objects is as likely as a small number of vast ones, maybe even more so?
As for the signed/unsigned question, I would usually favour unsigned (as
size_t is already an unsigned type), but that is partly conditioned by
having started out using C on 16-bit machines where that extra factor of
two was so much more important.
I also like the fact that the prototype then documents the fact that
negative values are erroneous.
> ================================== dynarray.h ==================================
> /* `a' is the array, declared as a pointer of the desired type and `data' is
> the contents of an array element. The functions returning `void*' return the
> new array variable, potentially modified due to reallocation. It is NULL in
> case of an error. */
> void* da_new ( size_t size ); /* create an empty array */
> void da_free ( void * a ); /* free an array */
>
> void* da_setlen( void * a, int len ); /* set the length */
> int da_len ( void * a ); /* get the length */
> void* da_add ( void * a, void * data ); /* add a new element */
> void* da_addemp( void * a, void ** data ); /* add an empty element */
>
> #include <stdlib.h>
> #include <string.h>
> #include "dynarray.h"
>
> ================================== dynarray.c ==================================
(I think something's got lost here. I think dynarray.c starts with
those three includes and there's a /* to be added also.)
> Memory layout:
> Field: [length][capacity][size ][data...]
> Type: int int size_t
> */
>
> /* ------------- Access to int and size_t with strict aliasing -------------- */
>
> union intalias
> { char cdata[sizeof(int)];
> int idata;
> };
I don't see the point of this union. The effective type of the
allocated storage is determined by the first modifying access, so if you
store an int at start, that will be the effective type of that part of
the storage.
(Mind you, I've always found the effective types rules confusingly
written so I may have got hold of the wrong end of the stick.)
> static void setint(void* dest, int val)
> { union intalias ia;
> ia.idata = val;
> memcpy(dest,ia.cdata, sizeof(int));
> }
>
> static int getint(void* source)
> { union intalias ia;
> memcpy(&ia, source, sizeof(int));
> return ia.idata;
> }
>
> union sizealias
> { char cdata[sizeof(size_t)];
> size_t sdata;
> };
>
> static void setsize(void* dest, size_t val)
> { union sizealias sa;
> sa.sdata = val;
> memcpy(dest,sa.cdata, sizeof(size_t));
> }
>
> static size_t getsize(void* source)
> { union sizealias sa;
> memcpy(&sa, source, sizeof(size_t));
> return sa.sdata;
> }
>
> /* ------------ Macros to access the fields of a dynamic array: ------------- */
> #define SHIFT(A,S) (((char*)A) - (S))
> #define OFFSET ( sizeof(size_t) + 2*sizeof(int))
> #define ORIGIN(A) SHIFT(A, OFFSET)
> #define GETLEN(A) getint (ORIGIN(A))
> #define GETSIZE(A) getsize(SHIFT((A),sizeof(size_t)))
> #define GETCAP(A) getint (SHIFT((A),sizeof(size_t)+sizeof(int)))
> #define SETLEN(A,L) setint (ORIGIN(A),(L))
> #define SETSIZE(A,S) setsize(SHIFT((A),sizeof(size_t)),S)
> #define SETCAP(A,C) setint (SHIFT((A),sizeof(size_t)+sizeof(int)),(C))
I'd simplify all this with a struct for the header.
<snip the rest of the code>
--
Ben.
[toc] | [prev] | [next] | [standalone]
Page 3 of 7 — ← Prev page 1 2 [3] 4 5 6 7 Next page →
Back to top | Article view | comp.lang.c
csiph-web