Segmentation fault when passing internal function

2019-02-20 03:49发布

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?

1条回答
倾城 Initia
2楼-- · 2019-02-20 04:22

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.

查看更多
登录 后发表回答