【问题标题】:Segmentation fault when passing internal function as argument将内部函数作为参数传递时出现分段错误
【发布时间】:2018-10-02 14:35:06
【问题描述】:

我有一些代码将主程序的内部函数作为参数传递给函数:当传递的函数最终被调用时,它会导致分段错误。这只发生在我使用适用于 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 上的一些非标准功能?

【问题讨论】:

  • 也许一些指针:stackoverflow.com/questions/40696534/… 和谷歌搜索“fortran 包含函数的范围”
  • 在 Fortran 2008 下允许内部过程(例如包含在主程序中的 f)作为实际参数,这在 gfortran 7 中实现。然后发生了其他事情。
  • 在我放弃 WSL 之前,我正在构建 gcc/g++/gfortran(由 WSL gcc 引导)以获得当前版本。尽管如此,WSL 还是有太多问题,所以我回到 cygwin 在 Windows 上进行 gfortran。
  • 我确实尝试了从 WSL 上的源代码构建的最新 svn 版本的 gfortran,但它仍然是一个问题。还在本机 linux 上尝试了 ifort 18 并且该测试通过了,所以似乎是 WSL 问题。
  • 截至 2020 年 11 月仍然存在问题。请参阅此页面:stackoverflow.com/questions/65066837/…

标签: fortran gfortran windows-subsystem-for-linux


【解决方案1】:

看起来我遇到了这个问题:

https://github.com/Microsoft/WSL/issues/3083https://github.com/Microsoft/WSL/issues/286

WSL 有一个不可执行的堆栈。运行:

excestack -c test

在本机 linux 上,要从二进制文件中删除 execstack,会触发与我在 WSL 上相同的错误消息。在 WSL 上清除/设置 execstack(使用 -c/-s)什么也不做。从 github 错误报告来看,它似乎不太可能被修复。

编辑:

似乎迁移到 WSL 版本 2 解决了这个问题

【讨论】:

  • 是的,内部函数通常使用蹦床传递,因此需要可执行堆栈。
猜你喜欢
  • 2021-05-13
  • 1970-01-01
  • 2016-12-20
  • 2014-12-10
  • 2013-07-26
  • 1970-01-01
  • 1970-01-01
  • 2013-05-06
  • 2023-03-08
相关资源
最近更新 更多