Path: utzoo!attcan!uunet!samsung!sol.ctr.columbia.edu!lll-winken!abhg!matrix!moler From: moler@matrix.mathworks.com (Cleve Moler) Newsgroups: comp.lang.fortran Subject: Re: Dimensioning arrays at run-time, best way? Summary: Need %loc() to use malloc with Fortran. Message-ID: <191@matrix.mathworks.com> Date: 18 Sep 90 23:23:20 GMT References: <1990Sep18.115704.20642@msuinfo.cl.msu.edu> Reply-To: moler@mathworks.com (Cleve Moler) Organization: The MathWorks Inc. Lines: 83 Hold it! Keith Bierman is really lucky if his program which uses malloc in Fortran works correctly. His program: > program example > > print*,"how many bytes ?" > read(*,*) nbytes > x=malloc(nbytes) > call realprog(x,nbytes/4) > end > subroutine realprog(x,n) > c > c this is where the "real program" begins > c > real x(n) > > c do processing, including all calls > c > return > end There are two things wrong with this. First, malloc returns an integer result, but "x" is, by default, of type real, so the assignment x = malloc(...) involves a conversion from integer to floating point. Second, and more important, the call to the subroutine passes the address of the scalar variable x, not the value of x which is the address of the allocated memory. So the subroutine uses n real locations beginning at the location of x, not at the location of the space obtained from malloc. It turns out that very simple instances of "realprog" might still appear to work because they don't clobber anything. The key to making this sort of thing work correctly is the VMS Fortran addressing extension %val(). This is a true extension to the language which must be handled by the compiler. It is not something you can just add to a run-time library. Fortunately, many manufacturers, including Bierman's employer, have adopted DEC's extension. (The idea was around before VMS Fortran, but everybody calls it a VMS extension today.) Here is a program that DOES work on my Sun SPARCstation 1. I've added a second array so something will get clobbered if the code isn't correct. program example integer x,y write(*,*) "enter n" read(*,*) n x = malloc(4*n) y = malloc(4*n) call realprog(%val(x),%val(y),n) end subroutine realprog(x,y,n) real x(n),y(n) do i = 1, n x(i) = i/10. y(i) = 10.*i enddo call wot(x,y,n) return end subroutine wot(x,y,n) real x(n),y(n) write(*,*) n,x(1),x(n),y(1),y(n) return end Note that x and y are declared to be integer in the main program. More importantly, note the use of %val() in the subroutine call. We have to pass the values of x and y, as obtained from malloc, down the line, rather than their locations, as would be the case in a conventional Fortran call. If you get rid of either the integer declaration, or the %loc()'s, the program will fail. (Trivia quiz: anybody know why my sub-subroutine is "wot"?) -- Cleve Moler moler@mathworks.com