Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #138077 > unrolled thread

Pointer conversion and alignment

Started byAnton Shepelev <anton.txt@gmail.com>
First post2018-11-17 14:38 +0300
Last post2018-11-19 14:33 -0800
Articles 20 on this page of 134 — 18 participants

Back to article view | Back to comp.lang.c


Contents

  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 →


#138417

FromRichard Damon <Richard@Damon-Family.org>
Date2018-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]


#138527

FromTim Rentsch <txr@alumni.caltech.edu>
Date2018-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]


#138530

FromRichard Damon <Richard@Damon-Family.org>
Date2018-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]


#138531

FromMalcolm McLean <malcolm.arthur.mclean@gmail.com>
Date2018-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]


#138534

FromDavid Brown <david.brown@hesbynett.no>
Date2018-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]


#138573

FromRichard Damon <Richard@Damon-Family.org>
Date2018-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]


#138533

FromAnton Shepelev <anton.txt@g{oogle}mail.com>
Date2018-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]


#138536

Fromscott@slp53.sl.home (Scott Lurndal)
Date2018-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]


#138561

FromKeith Thompson <kst-u@mib.org>
Date2018-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]


#138623

FromTim Rentsch <txr@alumni.caltech.edu>
Date2018-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]


#138628

FromRichard Damon <Richard@Damon-Family.org>
Date2018-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]


#138630

FromRichard Damon <Richard@Damon-Family.org>
Date2018-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]


#138631

FromKeith Thompson <kst-u@mib.org>
Date2018-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]


#138633

FromRichard Damon <Richard@Damon-Family.org>
Date2018-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]


#138714

FromTim Rentsch <txr@alumni.caltech.edu>
Date2018-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]


#138717

FromKeith Thompson <kst-u@mib.org>
Date2018-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]


#138718

FromTim Rentsch <txr@alumni.caltech.edu>
Date2018-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]


#138230

From"Chris M. Thomasson" <invalid_chris_thomasson@invalid.invalid>
Date2018-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(&region, 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]


#138110 — My dynamic arrays module [was:Re: Pointer conversion and alignment]

FromAnton Shepelev <anton.txt@gmail.com>
Date2018-11-19 02:26 +0300
SubjectMy 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]


#138111 — Re: My dynamic arrays module [was:Re: Pointer conversion and alignment]

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2018-11-19 11:08 +0000
SubjectRe: 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