I have some code that passes an internal function of the main program as an argument to a function: when the function that been passed is eventually called it causes a segmentation fault. This only occurs when I use Windows Subsystem for Linux (I'm using Ubuntu 16 on WSL); running on native Linux or Mac machines this does not occur.
A minimal example that crashes:
module test1
implicit none
contains
subroutine x(ff,y)
interface
real function ff(y)
real, intent(in) :: y
end function ff
end interface
real, intent(in) :: y
integer z
z=ff(y)
end subroutine x
end module test1
program tester
use test1
implicit none
call x(f,1.0)
contains
real function f(y)
real, intent(in) :: y
write(*,*) y
f=y*y
end function f
end program tester
Compiled with:
gfortran-7 -ggdb test_fun_passing.f90 -o test
The backtrace, gdb output:
(gdb) bt
#0 0x00007ffffffde320 in ?? ()
#1 0x0000000000400734 in test1::x (ff=0x7ffffffde320, y=1) at test_fun_passing.f90:17
#2 0x0000000000400829 in tester () at test_fun_passing.f90:31
#3 0x0000000000400860 in main (argc=1, argv=0x7ffffffde64f) at test_fun_passing.f90:27
#4 0x00007ffffec70830 in __libc_start_main (main=0x40082c <main>, argc=1, argv=0x7ffffffde448, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7ffffffde438) at ../csu/libc-start.c:291
#5 0x0000000000400669 in _start ()
This one does work (moving f into its own module but still passing as an argument) so it's something about f being contained in the program.
module test1
implicit none
contains
subroutine x(ff,y)
interface
real function ff(y)
real, intent(in) :: y
end function ff
end interface
real, intent(in) :: y
integer z
z=ff(y)
end subroutine x
end module test1
module test2
implicit none
contains
real function f(y)
real, intent(in) :: y
write(*,*) y
f=y*y
end function f
end module test2
program tester
use test1
use test2
implicit none
call x(f,1.0)
end program tester
gfortran-7 -ggdb test_fun_passing.f90 -o test && ./test
1.00000000
Is passing f in this way valid Fortran, or have I been relaying on some non-standard feature on native Linux?
Looks like I'm running into this:
https://github.com/Microsoft/WSL/issues/3083 and https://github.com/Microsoft/WSL/issues/286
WSL has a non-executable stack. Running:
excestack -c test
on native linux, to remove the execstack from the binary, triggers the same error message as I have on WSL. Clearing/setting the execstack (with -c/-s) on WSL does nothing. From the github bug report it seems its unlikely to be fixed.
Edit:
It seems moving to WSL version 2 fixes this issue
Related
The main program with too many subroutines and functions is existed. Some of the subroutines and functions also use subroutines, functions, and modules. I decided to write them in independent files due to clarity in the main program. Then I created an independent file as a module to collect them with the include command.
Now I have one main program and one independent file for the module. I compile the program but it shows an error. The error is about missing mentioned subroutine in the above independent file.
My question in general is: If you have a program with one main program and a number of sub-programs (subroutines, functions, and modules), which also they have sub-programs, what method do you use to assemble and run it?
I write my code in PLATO as a fortran95.
I will appreciate any comments that give me a little help and forgive me for writing shortcomings
What is the problem?
Consider the following structure.
On the independent file as the main program:
MAIN PROGRAM
CALL A
CALL B
CALL C
END PROGRAM
On the independent file as the subroutine A:
SUBROUTINE A
...
END SUBROUTINE
On the independent file as the subroutine B:
SUBROUTINE B
CALL B1
CALL B2
END SUBROUTINE
---------------
SUBROUTINE B1
...
END SUBROUTINE
--------------
FUNCTION B2
...
END FUNCTION
On the independent file as the subroutine C:
SUBROUTINE C
USE C1
CALL C2
END SUBROUTINE
---------------
SUBROUTINE C1
...
END SUBROUTINE
On the independent file as the module C1:
MODULE C1
CONTAINS
SUBROUTINE C1-1
SUBROUTINE C1-2
SUBROUTINE C1-3
...
END MODULE
What I did:
I created an independent file as Module:
MODUL D
INCLUDE A.F95
INCLUDE B.F95
INCLUDE C.F95
END MODULE
Consequently, for the main program:
MAIN PROGRAM
USE D
CALL A
CALL B
CALL C
END PROGRAM
What is the Error:
Warning: Missing A (File address), Missing B (File address), Missing C
(File address)
The following makefile should work for your setup.
FC := gfortran
main: c1.o d.o main.o
#$(FC) $^ -o main
main.o: main.f90 d.f90
#$(FC) -c $<
d.o: d.f90 a.f90 b.f90 c.f90 c1.o
#$(FC) -c $<
c1.o: c1.f90
#$(FC) -c $<
clean:
#rm -rf *.{o,mod} main
I used the following files (note the filenames and .f90 extensions)
! main.f90
program main
use d
print *, 'main'
call a()
call b()
call c()
end program
! b.f90
subroutine b()
logical :: tmp
print *, 'b'
call b1()
tmp = b2()
end subroutine
subroutine b1()
print *, 'b1'
end subroutine
logical function b2() ! added: function needs return type.
print *, 'b2'
b2 = .true.
end function
! c.f90
subroutine c()
use c1
print *, 'c'
call c1_1() ! added this line. otherwise module c1 would not be used at all.
call c2()
end subroutine
subroutine c2()
print *, 'c2'
end subroutine
! c1.f90
module c1
contains
subroutine c1_1()
print *, 'c1_1'
end subroutine
subroutine c1_2()
print *, 'c1_2'
end subroutine
subroutine c1_3()
print *, 'c1_3'
end subroutine
end module
! d.90
module d
contains ! added: files a.f90,b.d90,c.f90 define procedures and must be included after `contains`.
include 'a.f90'
include 'b.f90'
include 'c.f90'
end module
I am attempting to perform a 2D integral numerically using the quadpack double library. Since this website does not have a Latex engine integrated I attach a picture with the math.
I also attach below my implementation of this operation in the test_module module.
module test_module
use f90_kind ! defines dp
use physconst ! defines pi
use global_variables ! defines the variables for quadpack
use csv_file ! allows me to write to a csv file
implicit none
real(dp) :: a, b, c ! parameters I want to set
contains
real(dp) function multi_val_func(theta)
real(dp), intent(in) :: theta
multi_val_func = exp(theta**2 + c*theta)
end function multi_val_func
real(dp) function theta_integral(phi)
real(dp), intent(in) :: phi
c = phi*(a+b)
! Quadpack variables
epsabs = 1.0E-14_dp
epsrel = 0.0E0_dp
key = 6
ilow = 0.0E0_dp
ihigh = 2.0E0_dp*pi
call dqage(multi_val_func, ilow, ihigh, epsabs, epsrel, key, limit, &
res, abserr, neval, ier, alist, blist, rlist, elist, iord, last)
theta_integral = res
end function theta_integral
subroutine phi_integral(final_result)
real(dp),intent(out) :: final_result
a = 1.0E0_dp
b = 1.0E0_dp
! Quadpack variables
epsabs = 1.0E-14_dp
epsrel = 0.0E0_dp
key = 6
ilow = 0.0E0_dp
ihigh = pi
call dqage(theta_integral, ilow, ihigh, epsabs, epsrel, key, limit, &
res, abserr, neval, ier, alist, blist, rlist, elist, iord, last)
final_result = res
print *, final_result
end subroutine phi_integral
end module test_module
In the main file I define the result variable and thereafter call phi_integral(result). I compile this code using the following makefile
FFLAGS = -O0 -fcheck=all -ffree-line-length-none
debug:
gfortran -c $(FFLAGS) $(srcdir)/f90_kind.f90
gfortran -c $(FFLAGS) $(srcdir)/physconst.f90
gfortran -c $(FFLAGS) $(srcdir)/global_variables.f90
gfortran -c $(FFLAGS) $(extlib_qp)/quadpack_double.f90
gfortran -c $(FFLAGS) $(extlib_csv)/csv_file.f90
gfortran -c $(FFLAGS) $(srcdir)/multi_var_integration.f90
gfortran -c $(FFLAGS) $(srcdir)/main.f90
gfortran *.o -o debug -lblas -llapack
rm -f *.o *.mod
The code compiles but when I run it I receive the following error:
Fortran runtime error: Recursive call to nonrecursive procedure 'dqage'
Error termination. Backtrace:
#0 0x103a28d3d
#1 0x103a299f5
#2 0x103a29fd6
#3 0x1039f94b6
#4 0x1039dee59
#5 0x1039fad68
#6 0x1039f9948
#7 0x1039dec7d
#8 0x1039def61
#9 0x1039defa3
Any suggestion for dealing with this is greatly appreciated.
Not every subroutine or function in Fortran is re-entrant or, as Fortran calls it, "recursive". Before Fortran 2018 a subroutine that can be called, when already inside itself (even if indirectly) must be marked by the recursive attribute.
Even if a subroutine is marked that way, it may not work as expected if it contains static (saved) data or if it uses global (common blocks, module) variables.
I cannot immediately see any such static data used in http://www.netlib.no/netlib/quadpack/dqage.f so it might actually work after adding recursive.
However, as francescalus pointed out, you should be better off with a dedicated 2d quadrature library.
The theta integral can be done via the error function erf. See wolfram alpha.
The result of that is a function of one variable phi which can be evaluated via quadpack. Thus, you don't need a multidimensional integral routine after all.
I have a C program that has a function named get_name. This function returns a string (i.e. char *) and changes the argument size (passed to it) with the size of the string:
char *get_name(int &size)
{
*size = strlen(name); // name is a C global variable declared as a char *
return name;
}
I have created the following Fortran module to be able to call the C function get_name:
MODULE X
USE, INTRINSIC :: iso_c_binding, ONLY: c_intptr_t
IMPLICIT NONE
INTERFACE
TYPE(c_ptr) FUNCTION get_name_(size) BIND(C, name = "get_name")
USE, INTRINSIC :: iso_c_binding, ONLY: c_int, c_ptr
INTEGER(c_int), INTENT(OUT) :: size
END FUNCTION
END INTERFACE
CONTAINS
FUNCTION get_name()
USE, INTRINSIC :: iso_c_binding, ONLY: c_int, c_char, c_f_pointer, c_ptr, c_associated
!DEC$ ATTRIBUTES DLLEXPORT :: get_name
CHARACTER(LEN = :), ALLOCATABLE :: get_name
INTEGER(c_int) :: size
TYPE(c_ptr) :: c_string
c_string = get_name_(size)
IF (c_associated(c_string)) THEN
BLOCK
CHARACTER(KIND = c_char, LEN = size), POINTER :: f_string
CALL c_f_pointer(c_string, f_string)
get_name = f_string
END BLOCK
ELSE
get_name = ""
END IF
END FUNCTION
END MODULE
I can successfully compile this Fortran module using IFORT 2016 in Windows, IFORT 2016 in Linux, and gfortran in Linux.
To test things, I have created a short Fortran program:
PROGRAM Test
USE X
WRITE(*, *) "Name: ", get_name()
END PROGRAM
I can successfully compile this Fortran program using IFORT 2016 in Windows, IFORT 2016 in Linux, and gfortran in Linux.
Now, when running the program it works well in IFORT 2016 for Linux, gfortran in Linux, but not in IFORT 2016 for Windows. It actually gives the following error:
forrtl: severe (157): Program Exception - access violation
Any idea how this error can be solved?
I assume your C function is char *get_name(int *size) instead of using a C++ reference.
Then this code works here on Windows and Linux with Ifort 16 and gcc-6.3.1 or Visual Studio 2015.
Please add your used C compiler and command lines to compile the code. I used:
cl -c testc.c && ifort -c testf.f /extend-source:132 && ifort testm.f testf.obj testc.obj /extend-source:132 && testm.exe
Btw: If you are using this function in parallel code I would suggest to avoid the block construct - I had bad experience using this in parallel (OpenMP) code with Ifort 16.
I'm experiencing a problem since I'm trying to run my fortran code with ifort, which was previously compiled with gfortran. One of my code's functions is using an other function as an argument, as shown below. Compiling the code with gfortran/ifort do not generate any errors.
module mod_rk4_2
implicit none
contains
!rk4 temporal scheme
function rk4(f,dt,func) result(f_new)
double precision, dimension(:,:), intent(in) :: f
double precision, intent(in) :: dt
double precision, dimension(size(f,1),size(f,2)) :: f_new
double precision, dimension(:,:), allocatable :: k1, k2, k3, k4
interface
function func(f) result(res)
double precision, dimension(:,:), intent(in) :: f
double precision, dimension(size(f,1),size(f,2)) :: res
end function func
end interface
allocate(k1(size(f,1),size(f,2)),k2(size(f,1),size(f,2)),k3(size(f,1),size(f,2)),k4(size(f,1),size(f,2)))
k1=func(f)
k2=func(f+dt*k1/2)
k3=func(f+dt*k2/2)
k4=func(f+dt*k3)
f_new=f+dt/6*(k1+2*k2+2*k3+k4)
deallocate(k1,k2,k3,k4)
end function rk4
end module mod_rk4_2
Running the code compiled with gfortran is fine, but when compiled with ifort, the code crashes at the first call of the forementioned function, with a stack overflow error message. Any ideas ?
forrtl: severe (170): Program Exception - stack overflow
Image PC Routine Line Source
main 00007FF779CCAE38 Unknown Unknown Unknown
main 00007FF779C564E0 Unknown Unknown Unknown
main 00007FF779CCAC02 Unknown Unknown Unknown
main 00007FF779CCB04C Unknown Unknown Unknown
KERNEL32.DLL 00007FF9D8EC1FE4 Unknown Unknown Unknown
ntdll.dll 00007FF9D99BEFC1 Unknown Unknown Unknown
I am trying to compile a fortran module with f2py. It is the following code
module my_log_mod
implicit none
interface my_log
module procedure my_log_array
module procedure my_log_vector
end interface my_log
private ! hides items not listed on public statement
public :: my_log
contains
subroutine my_log_array(a,res)
double precision, dimension (:,:), intent (in) :: a
double precision, dimension (:,:), intent (out) :: res
where (a>1.0)
res = log(a)
else where
res = 0.D0
end where
end subroutine
subroutine my_log_vector(a,res)
double precision, dimension (:), intent (in) :: a
double precision, dimension (:), intent (out) :: res
where (a>1.0)
res = log(a)
else where
res = 0.D0
end where
end subroutine
end module my_log_mod
that I compile with the following command
f2py.py -c -m my_log_mod_comp my_log_mod.f90
and it results in the following error
C:\Users\weisshau\AppData\Local\Temp\tmpf0apqa7s\src.win32-3.6\my_log_mod_comp-f2pywrappers2.f90:7:28:
use my_log_mod, only : my_log_array
1
Error: Symbol 'my_log_array' referenced at (1) not found in module 'my_log_mod'
C:\Users\weisshau\AppData\Local\Temp\tmpf0apqa7s\src.win32-3.6\my_log_mod_comp-f2pywrappers2.f90:18:28:
use my_log_mod, only : my_log_vector
1
Error: Symbol 'my_log_vector' referenced at (1) not found in module 'my_log_mod'
I don't really know much about fortran and f2py, so I don't have any idea what is happening. If i use the module in pure fortran it works nicely
F2py appears to be creating another wrapper code which uses the subroutines in your module.
But it calls directly the subroutines my_log_vector and my_log_array. It seems f2py does not support private. I would delete the private.
Also be prepared that you won't be able to use the generic my_log in Python. This concept of generics is alien to Python. You may need to delete the generic interface if deleting private does not make it compilable. You should definitely delete the public :: my_log.
Unfortunately, f2py does not support all features of modern Fortran.
The code I tested:
module my_log_mod
implicit none
interface my_log
module procedure my_log_array
module procedure my_log_vector
end interface my_log
contains
subroutine my_log_array(a,res)
double precision, dimension (:,:), intent (in) :: a
double precision, dimension (:,:), intent (out) :: res
where (a>1.0)
res = log(a)
else where
res = 0.D0
end where
end subroutine
subroutine my_log_vector(a,res)
double precision, dimension (:), intent (in) :: a
double precision, dimension (:), intent (out) :: res
where (a>1.0)
res = log(a)
else where
res = 0.D0
end where
end subroutine
end module my_log_mod
compilation:
f2py -c -m my_log_mod_comp my_log_mod.f90
...
Post-processing...
Block: my_log_mod_comp
Block: my_log_mod
Block: my_log
Block: my_log_array
Block: my_log_vector
Post-processing (stage 2)...
Block: my_log_mod_comp
Block: unknown_interface
Block: my_log_mod
Block: my_log_array
Block: my_log_vector
Building modules...
Building module "my_log_mod_comp"...
Constructing F90 module support for "my_log_mod"...
Creating wrapper for Fortran subroutine "my_log_array"
res = my_log_array(a)
res = my_log_array(a)
Creating wrapper for Fortran subroutine "my_log_vector"("my_log_vector")...
Constructing wrapper function "my_log_mod.my_log_vector"...
res = my_log_vector(a)
Wrote C/API module "my_log_mod_comp" to file "/tmp/tmp7e5v0u/src.linux-x86_64-2.7/my_log_mod_compmodule.c"
Fortran 90 wrappers are saved to "/tmp/tmp7e5v0u/src.linux-x86_64-2.7/my_log_mod_comp-f2pywrappers2.f90"
...
gfortran:f90: /tmp/tmp7e5v0u/src.linux-x86_64-2.7/my_log_mod_comp-f2pywrappers2.f90
/usr/bin/gfortran -Wall -g -Wall -g -shared /tmp/tmp7e5v0u/tmp/tmp7e5v0u/src.linux-x86_64-2.7/my_log_mod_compmodule.o /tmp/tmp7e5v0u/tmp/tmp7e5v0u/src.linux-x86_64-2.7/fortranobject.o /tmp/tmp7e5v0u/my_log_mod.o /tmp/tmp7e5v0u/tmp/tmp7e5v0u/src.linux-x86_64-2.7/my_log_mod_comp-f2pywrappers2.o -L/usr/lib64 -lpython2.7 -lgfortran -o ./my_log_mod_comp.so
Removing build directory /tmp/tmp7e5v0u