将内部函数作为参数传递时出现分段错误
Segmentation fault when passing internal function as argument
我有一些代码将主程序的内部函数作为参数传递给函数:当传递的函数最终被调用时,它会导致分段错误。这仅在我为 Linux 使用 Windows 子系统时发生(我在 WSL 上使用 Ubuntu 16); 运行 在本机 Linux 或 Mac 机器上不会发生这种情况。
一个最小的崩溃示例:
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
编译:
gfortran-7 -ggdb test_fun_passing.f90 -o test
回溯,gdb 输出:
(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 ()
这个确实有效(将 f
移动到它自己的模块中但仍然作为参数传递)所以它是关于 f
被包含在程序中的东西。
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
以这种方式传递 f
是有效的 Fortran,还是我一直在依赖原生 Linux 上的一些非标准功能?
看起来我 运行 喜欢这个:
https://github.com/Microsoft/WSL/issues/3083 and https://github.com/Microsoft/WSL/issues/286
WSL 有一个不可执行的堆栈。 运行:
excestack -c test
在本机 linux 上,要从二进制文件中删除 execstack,会触发与我在 WSL 上相同的错误消息。 Clearing/setting WSL 上的 execstack(带有 -c/-s)什么都不做。从 github 错误报告来看,它似乎不太可能被修复。
编辑:
转移到 WSL 版本 2 似乎解决了这个问题
我有一些代码将主程序的内部函数作为参数传递给函数:当传递的函数最终被调用时,它会导致分段错误。这仅在我为 Linux 使用 Windows 子系统时发生(我在 WSL 上使用 Ubuntu 16); 运行 在本机 Linux 或 Mac 机器上不会发生这种情况。
一个最小的崩溃示例:
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
编译:
gfortran-7 -ggdb test_fun_passing.f90 -o test
回溯,gdb 输出:
(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 ()
这个确实有效(将 f
移动到它自己的模块中但仍然作为参数传递)所以它是关于 f
被包含在程序中的东西。
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
以这种方式传递 f
是有效的 Fortran,还是我一直在依赖原生 Linux 上的一些非标准功能?
看起来我 运行 喜欢这个:
https://github.com/Microsoft/WSL/issues/3083 and https://github.com/Microsoft/WSL/issues/286
WSL 有一个不可执行的堆栈。 运行:
excestack -c test
在本机 linux 上,要从二进制文件中删除 execstack,会触发与我在 WSL 上相同的错误消息。 Clearing/setting WSL 上的 execstack(带有 -c/-s)什么都不做。从 github 错误报告来看,它似乎不太可能被修复。
编辑:
转移到 WSL 版本 2 似乎解决了这个问题