[comp.lang.fortran] Fun with pointers

tp@mccall.com (09/07/90)

Alternate way to do it below. This is just as gross, so don't flame about
it. I inherited code similar to the original posting and had to port it. It
was too big to rewrite. My main objection was the fixed size array. Too
small, and you crash, too big and you waste mucho memory.

Using the same assumption (subscript checking can be defeated), if you have
a memory allocator (lib$get_vm on VMS, malloc on unix), just use it. What
you do is declare blank common like so:

      COMMON // IMEM(1)

Put that in the allocator and all routines that use dynamic memory (i.e.
with an include file). In your allocator, allocate a block of memory and
then determine what subscript for array imem is needed to access the
allocated memory (that's the magic part, but can be solved easily with an
assembler or C subroutine if your fortran doesn't have the appropriate
extentions). Return that value. Your code then accesses dynamic memory by
accessing IMEM(ADDR+OFFSET). 

Note that you can define "structures" by declaring the imem array larger
and equivalencing things to it. Then you can use the same offset for all
the members of the structure to get to all the various locations (be sure
to increment it properly!).

Just to catch errors with this setup, I actually have the IMEM array itself
set up as read-only memory (on VMS, don't know how you'd do that on unix)
so that using a "reasonable" subscript with it will fail.

It's a major hack, but so is what he proposed, and this at least can save
some statically allocated memory.
-- 
Terry Poot <tp@mccall.com>                The McCall Pattern Company
(uucp: ...!rutgers!ksuvax1!mccall!tp)     615 McCall Road
(800)255-2762, in KS (913)776-4041        Manhattan, KS 66502, USA

3003jalp@ucsbuxa.ucsb.edu (Applied Magnetics) (09/08/90)

Preamble:  suppose I do this in a subroutine:

  integer bcbase    ! "Blank Common BASE"
  common//bcbase
  integer      link(0:3),     nwords(0:0),      content(0:0, 1)
  equivalence (link,bcbase), (nwords,link(1)), (content,link(2))

And, in the main program,

  integer scratch(1000000)  ! one million
  common//scratch

Now I can have the routine divide the blank common into unequal-sized
blocks, and link them in a list.  If a block of N words begins at offset
P in blank common, I set up

  link(P)= <offset to next block>
  nwords(P)= N
  content(P,k)= <anything I want, k= 1, N-2>

The equivalence statements force the memory layout to be what I want.
Link(P) is at offset P;  nwords(P) is at offset P+1; content(P,k) is
at offset P+2+(k-1).  More generally, I can use integer offsets into
blank common as substitute for pointers;  I can imitate C's operator
"->" and dereference mock-pointers to structure components;
I can manage nontrivial data structures dynamically, as long as the
primitive types are restricted to integer, logical, real or double
precision (more tricks needed for the latter).

Critical assessment:
The ANSI standard says that overrunning arrays like I do produces
undefined results (17.1.2).  THIS IS A CASE OF USING THE WRONG
LANGUAGE.  DO NOT TRY IT AT HOME.  I actually wrote code that way, but
only because I have to.  I'll be migrating away from it the first
chance I get.

End of preamble.

Question:
Assuming that any run-time checking of array bounds can be defeated,
are there extant implementations of Fortran that would foil my evil
designs?  Just curious.

  --Pierre Asselin, Applied Magnetics Corp.

3003jalp@ucsbuxa.ucsb.edu (Applied Magnetics) (09/12/90)

(Did my post show up a second time without a header?  Sorry)

In a reply to my "pointers" post, Terry Poot suggests using a memory
allocator to get rid of static arrays.  I am indeed using a memory
allocator, but that's another story.

My question is:  can you overrun the declared bounds of an array and
get away with it?  The standard says no.  The effects of an equivalence
are undefined once you step out of bounds.

Stephen Walton says that Microsoft Fortran on MS-DOS will see my
link(0:3) or Terry's IMEM(1) and decide to use 16-bit arithmetic to
compute offsets into such small arrays.  Trouble City.  That's the sort
of thing I am after.

  --PA