从gdb调用派生类型的fortran子例程



我想调用一个函数,该函数将Gnu调试器(gdb(中的派生类型作为参数。我最终得了segfault。这是一个";最小值";工作示例:

module modSimpleClass
type Person
character(len=20) :: Name
contains
procedure PrintName
end type
contains
subroutine PrintName(a)
class(Person) :: a
print *, a%Name
end subroutine
subroutine Print42()
print *, "42"
end subroutine
subroutine PrintNameFromOutside(a)
class(Person) :: a
print *, a%Name
end subroutine
end module
program testgdb
use modSimpleClass
implicit none
type(Person) :: JoeJohnson
JoeJohnson%Name = "Joe Johnson"
call JoeJohnson%PrintName
end program testgdb

我用gfortran版本9.3.0编译它,从gdb运行它,并在它结束之前停止它。以下内容有效:

call Print42()
print JoeJohnson%Name

以下内容不起作用:

call JoeJohnson%PrintName()!There is no member named PrintName.
call PrintName(JoeJohnson)!Error then segfault
call PrintNameFromOutside(JoeJohnson)!Error then segfault

错误如下:

正在调试的程序在从GDB调用的函数中发出信号。GDB保留在接收到信号的帧中。为了改变这种行为,使用";将unundnsignal设置为"打开";。包含函数的表达式的求值(modsimpleclass::printname(将被放弃。当函数执行完毕时,GDB将自动停止。

如何从gdb正确调用fortran子例程?


感谢您对Flusslauf的回复。我将试着改写你所说的:

从gfortran的角度来看,如果我们在模块modsimpleclass中定义了派生类型Person

  • 只有初始化变量的作用域才能看到原始类型
  • 任何作为参数的函数或子程序该派生类型的对象的类型为__class_modsimpleclass_Person_t具有属性:
    1. _data:指向对象的指针
    2. _vptr:指向包含对象信息的对象的指针

因此,函数实际上为派生类型的每个对象获取两个指针:一个指向对象另一个指向关于对象的信息。

从gdb向函数传递指向对象的指针是有效的,但是将对象本身传递给它是不起作用的。


@Flusslauf建立

call PrintName( &JoeJohnson )!works because it is equivalent to
call PrintName( a%_data )!this, which works too
call PrintName( a )!this works and it makes sense
call PrintName( a%_data, a%_vptr )!this also works
call PrintName( a%_vptr)!this outputs something strange
call PrintName( *(a%_data) )!causes segfault since equivalent to
call PrintName( JoeJohnson )!Error then segfault

,其中每个指令都在变量的正确范围内执行。

这里的问题是,虽然正常的Fortran语法允许调用PrintName(JoeJohnson),但传递参数的实际类型似乎是(在printname中设置断点并编译gfortran(

Breakpoint 1, modsimpleclass::printname (a=...) at ./stack.f90:10
10                  print *, a%Name
(gdb) ptype a
type = Type __class_modsimpleclass_Person_t
PTR TO -> ( Type person :: _data )
PTR TO -> ( Type __vtype_modsimpleclass_Person :: _vptr )
End Type __class_modsimpleclass_Person_t

而CCD_ 7的类型是非指针类型。我想上面的类型是gfortran在Fortran中传递类型参数的方法。

在上述情况下,

PrintName(&JoeJohnson)

可以工作,但很烦人。。


编辑:

只是为了完成-ifx/ifort实际上似乎为传递的参数使用了一个指针

(gdb) ptype a
type = PTR TO -> ( Type person
character*20 :: name
void :: printname(void)
End Type person )

因此执行CCD_ 8将不再那么麻烦(GDB在使用ifx/ifort编译时无法解析PrintName(。我不确定是否可以以一种有意义的方式调整gdb以允许这种调用。由于参数处理和调用语法依赖于编译器。

最新更新