From: cummings@tiger1.prime.com (Kevin J. Cummings)
Subject: Re: Demonstration of ANSI C restriction on pointers
Organization: Prime Computer, Inc.
Date: Mon, 14 Sep 1992 18:24:43 GMT

In article <9209111203.AA29161@usenet.rpi.edu>, GORMAN_B@prime1.lancashire-poly.ac.uk (Barry Gorman) writes:
> This is a little fragment to demonstrate the restriction in ANSI c that a
> pointer is not allowed to point before the start of an array. It doesnt
> always crash, clean-up all your dynamic segments first.
> 
> Barry
> .....
> 
> ---------------------------------------------------------------------------
> 
> char *malloc();
> typedef struct {int first; char rest[60];} object;
> main(){object *p=(object*)malloc(sizeof(object)*10);
>     printf("%p\n", p); --p; printf("%p\n", p); p[2].first=0;}

Are you saying that the decrement of the pointer and the use of the pointer
in an array context don't use the same type of arithmetic to do the
offsetting?  The code I saw for the pointer decrement was:

000036: 002241.000046s            L       R1, SB%+046
000040: 044205.000040             S       R1, =040L
000042: 042241.000046s            ST      R1, SB%+046

Note the use of 32 bit arithmetic.  This will cause segment crossing if the
initial pointer value is "close enough" to the beginning of a segment.
(Is that why you suggested "clean-up all your dynamic segments first"?)
Then the reference to p[2].first is done via GRR addressing:

000060: 002241.000046s            L       R1, SB%+046
000062: 114607.000100             ZM      R1+0100,*

which I beleive wraps within a segment.  This does not mean that "a pointer is
not allowed to point before the start of an array" (though I can beleive
that this test case will fail when run with a clean heap).  I will contact the
appropriate people to find out why the compiler uses two different methods of
addressing.  I will report back when I get an answer.

Your program doesn't always crash, but your assignment does always trash
unallocated memory (if it succeeds).  Since the heap storage uses a boundary-tag
method of allocating memory, you are most likely trashing your boundary tags,
or the boundary tags of another piece of allocated memory in the case where your
pointer does NOT change segments, OR you are trashing a location in
a different segment, and the result will depend on what got trashed.  It is
possible to take an pointer condition based on the segment being referenced.

You realize that p[2] references memory beyond what you allocated, yes?
In that case I'm not surprised at all that your test case will "crash"
sometimes when run.  This is a symptom of any program that tries to manipulate
memory beyond what was allocated for it.  However I do agree that the
compiler is using inter-segement addressing when decrementing the pointer,
and intra-segment addressing when dereferencing the pointer.

=================================================================
Kevin J. Cummings                       PrimeService
20 Briarwood Road                       A Computervision Company
Framingham, Mass.                       500 Old Connecticut Path
					Framingham, Mass.
Work:  cummings@primerd.Prime.COM
Home:  cummings@kjc386.framingham.ma.us

Std. Disclaimer: "Mr. McKittrick, after careful consideration,
		  I've come to the conclusion that your new
		  defense system SUCKS..."   --  War Games
=================================================================
Newsgroups: comp.sys.prime