Fortran使用gdb从地址打印函数名

3

假设我有如下代码:

module eval_mod
    implicit none(type, external)
    private
    public :: eval
    abstract interface
        real pure function real_function_t(x)
            real, intent(in) :: x
        end function
    end interface

contains

    pure function eval(f, x) result(res)
        procedure(real_function_t) :: f
        real, intent(in) :: x
        real :: res
        res = f(x)
    end function

end module

program main
    use iso_fortran_env, only: stdout => output_unit
    use eval_mod, only: eval
    implicit none(type, external)

    write(stdout, *) eval(double, 2.)
    write(stdout, *) eval(triple, 2.)

contains

    pure real function double(x)
        real, intent(in) :: x
        double = 2. * x
    end function

    pure real function triple(x)
        real, intent(in) :: x
        triple = 3. * x
    end function

end program

使用gfortran -Wall -Wextra -Werror -g -fbounds-check编译它。

如果我为eval_mod::eval设置断点,我想看到哪个函数参数调用了eval

实际上我看到的是:

Breakpoint 2, eval_mod::eval (f=0x7fffffffced8, x=2) at main.F90:17

如果我获取地址并按照这篇问题中的步骤,我应该能够通过执行以下命令在符号表中查看函数名:

info symbol 0x7fffffffced8

不幸地,我遇到了一个错误

No symbol matches 0x7fffffffced8.

如何查看作为参数传递的函数的函数名?

PS:我使用 gfortran 7.5.0 和 gdb 11.1。

1个回答

5

doubletriple内部函数(在主程序内部)。传递内部函数比较棘手,因为变量从父级作用域中关联到宿主。因此,它们经常使用跳板实现。您看到的地址是跳板的地址,换句话说,是所谓的thunk。跳板然后调用实际函数。

该地址很可能指向堆栈上放置跳板代码的某个位置。在该代码中,您可能会找到一个具有实际函数地址的跳转指令。

请参阅Steve Lionel的这篇优秀文章 Doctor Fortran in “Think, Thank, Thunk”


我可以确认,如果我将函数double和triple放入模块而不是主程序中,我在第一次调用时可以正确地在gdb中获得eval_mod :: eval(f = 0x400900 <eval_mod::double>, x = 2)。非常感谢! - mcocdawc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接