On Wednesday, June 1, 2022 at 8:24:36 AM UTC-7, Ron Shepard wrote:
(snip)
> Others have already stated how it violates the C standard. The reason
> for this restriction in C was that the array concept was based on a
> segmented memory model.
Well, even more than segmented, there used to be machines with
a tagged memory model. Each location had tags as to what kind
of value was stored there.
> If the first element of the array happened to be
> at a segment boundary, then decrementing the pointer meant that the
> address was no longer necessarily even within the program's address
> space.
Well, this could happen even without segmented memory, if the
array happened to be at the bottom of memory.
(To get back to the topic of this group, early Fortran compilers
allocated memory from the top of the address space down. Arrays
were stored in decreasing addresses in memory.)
In any case, yes, with protected mode x86, you can't load a segment
selector that doesn't select a valid segment descriptor, except for
the null selector, 0. In large model, though, only the offset is changed
with pointer arithmetic. In huge model, it will also change the
segment number. Even so, though, compilers usually won't load a
selector until you actually reference it, mostly because of code
like that. C guarantees that you can have a pointer to one past the
end of an array, and, more specifically, that it compares greater
than pointers into the array. That allows for loop tests based
on pointer values. Also, C doesn't allow (or doesn't define the
effect of) comparing pointers to different data items.
In the 80286 days, I was running OS/2 1.0 or 1.2, and allocating
segment selectors directly from the OS, with the exact length.
It was, then, a hardware exception even reading an array element
outside the array, and with no extra overhead. Very good for debugging
programs that might not be so good with array references.
> Depending on the OS, it could be pointing at some part of the OS,
> or in a multitasking environment to the memory of another process. Then
> later when virtual memory became popular, it could have resulted in page
> address violations, depending on how exactly the virtual and actual
> memory were mapped to each other.
Protected mode x86 is based on segments with a selector
and length. But as above, compilers would avoid unneeded
selector access to avoid the problem.
> Such address computations could
> trigger errors, even if the pointers were never referenced. The upper
> range of the pointers were accounted for in the language. I think the
> restriction was that the pointer was allowed to go one unit outside of
> the array bound, but it could not be dereferenced once it was there.
Yes. And so one less than the addressable space.
> There was no such allowance for the lower bound of the array, the
> language simply did not allow the pointer outside that range, whether or
> not it was later referenced or, as in the above example, incremented
> back to within the valid array range.
As above, compilers were good at avoiding that, but even so it can
still cause problems. Large model 16 bit x86 code only changes the offset,
and for other than equality and inequality, only compares the offset.
Even though it doesn't generate any access problems, the comparison
can fail.