When do Fortran module allocatable arrays go out of scope when loaded as a shared library?

早过忘川 提交于 2019-12-23 18:46:02

问题


I am calling a fortran subroutine from R as part of a more complex optimization problem. Currently, the subroutine is self-contained -- with an input of current parameter values and an output of function evaluation and gradient terms. I now wish to initialize an allocatable array as a shared module variable (prior to the optimization) that will be used (but not modified) by the subroutine during optimization.

In this context, when would the shared allocatable array go out of scope or be deleted?

A naive reading of the memory management section of Fortran wikibook suggests that module variables should persist (possibly even after a program has been executed).

A number of sources I've read indicate that an allocatable array will be deallocated automatically when it goes out of scope. Does this happen for module variables as well and when would this happen?

I've found a number of related questions but I haven't been able to place them in context of both module variables and shared library loading.

Edit:

A minimal example of the fortran module. The allocated array works as expected in a fortran program. In practice, both init() and eval() will be wrapped by R functions (init_wrap() and eval_wrap()) and called from R. I want to confirm that the allocated variable y is guaranteed not to go out of scope or get deleted while test_module is loaded as a shared library.

module test_module

  double precision, allocatable, dimension(:,:) :: y

  contains

    subroutine init() bind(C, name = "init_")

      if (.not. allocated(y) ) then
        allocate(y(1,1))
      end if

      y = 1
    end subroutine init

    subroutine eval(x, z) bind(C, name = "eval_")

      double precision, intent(in) :: x
      double precision, intent(out) :: z

      z = x + y(1,1)

    end subroutine eval

end module test_module

! Program added for testing purposes only, 
! module is used as shared library
program test_program

   use test_module

   double precision :: x, z

   ! Initialize allocatable array
   call init()

   ! Use allocatable array during optimization
   x = 1
   call eval(x, z)

   x = 2
   call eval(x, z)

   print *, z

end program test_program

Edit 2:

I've created a skeleton package on github that models how I'm using fortran code: https://github.com/ssokolen/fortran.test

The following R code works as I need it to (the allocated array keeps its value between eval_wrap() calls), but I'm still hoping to get a definitive answer on when an allocated module variable would go out of scope when loaded as a shared library (or an answer that states that there is no general behaviour).

library(devtools)
install_github('ssokolen/fortran.test')
library(fortran.test)
init_wrap()
eval_wrap(1)
eval_wrap(2)

回答1:


Dynamically loaded libraries are beyond Fortran standard. What happens indicated by the whole "processor" which is the complex of Fortran compiler, operating system, linker and so on.

In Linux and other POSIX operating systems, if you unload the library from memory, it will go out of scope. This simple test case demonstrates that:

module test_module

  double precision, allocatable, dimension(:,:) :: y

  contains

    subroutine init() bind(C, name = "init_")
      print *, "init_"
      if (.not. allocated(y) ) then
        allocate(y(1,1))
      end if

      y = 1
    end subroutine init

    subroutine eval(x, z) bind(C, name = "eval_")

      double precision, intent(in) :: x
      double precision, intent(out) :: z

      if (.not. allocated(y) ) error stop("not allocated!")
      z = x + y(1,1)
      print*, "success"
    end subroutine eval

end module test_module

And C calling the library:

#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>

int main(){

  void *handle = dlopen("/home/lada/f/testy/stackoverflow/dltest.so",RTLD_NOW);

  void (*init_)() = (void (*)())dlsym(handle, "init_");
  init_();

  double x=0,y=0;
  void (*eval_)(double x, double z) = (void (*)())dlsym(handle, "eval_");      
  eval_(x, y);

  dlclose(handle);
  handle = dlopen("./dltest.so",RTLD_NOW);

  eval_ = (void (*)())dlsym(handle, "eval_");
  eval_(x, y);

  return 0;

}

And run:

> gfortran -shared -fPIC -o dltest.so dltest.f90
> gcc -ggdb  dltest.c -ldl
> ./a.out 
 init_
 success
ERROR STOP not allocated!

The array is no longer allocated after dlclose() and dlopen(). You must make sure that R will not unload the library from memory.



来源:https://stackoverflow.com/questions/44304714/when-do-fortran-module-allocatable-arrays-go-out-of-scope-when-loaded-as-a-share

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!