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