问题
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