I want to call a function that takes as an argument a derived type from within the Gnu Debugger (gdb). I eventually get a segfault. Here's a "minimum" working example:
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
I compile it with gfortran version 9.3.0, run it from gdb and stop it before its end. The following things work:
call Print42()
print JoeJohnson%Name
The following things don't work:
call JoeJohnson%PrintName()!There is no member named PrintName.
call PrintName(JoeJohnson)!Error then segfault
call PrintNameFromOutside(JoeJohnson)!Error then segfault
The error is as follows:
The program being debugged was signaled while in a function called from GDB. GDB remains in the frame where the signal was received. To change this behavior use "set unwindonsignal on". Evaluation of the expression containing the function (modsimpleclass::printname) will be abandoned. When the function is done executing, GDB will silently stop.
How to correctly call fortran subroutines from gdb?
Thank you for you response @Flusslauf. I am going to try to rephrase what you said:
From the point of view of gfortran, if we have the derived type Person
defined in module modsimpleclass
,
- Only the scope in which the variable is initialized sees the original type.
- Any function or subroutine which takes as an argument
an object of that derived type sees the type
__class_modsimpleclass_Person_t
with attributes:_data
: A pointer to the object._vptr
: A pointer to something that has information about the object.
So a function really takes two pointers for each object of a derived type: one which points to the object and another one which points to information about the object.
From gdb, passing to a function a pointer to the object works, but passing to it the object itself doesn't work.
@Flusslauf established
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
, where each instruction is executed in the correct scope for the variable.