I am testing the PGI Fortran 19.10 compiler.
And I get a segmentation fault after compilation with PGI when I run the file named test.f90 ; while when I compile and run with gfortran or ifort I get no problem.
the filetest.f90:
MODULE modu
IMPLICIT NONE
! Format
type, abstract :: FormatFile
contains
procedure(File_open_file),nopass, deferred :: open_files
end type FormatFile
type, extends(FormatFile) :: FormatA
contains
procedure, nopass :: open_files => open_fileA
end type FormatA
! Type
type, abstract :: TypeFile
class(FormatFile), allocatable :: format
end type TypeFile
type, extends(TypeFile) :: TypeB
end type TypeB
! FileHandler
type, public :: FileHandler
private
class(TypeFile), allocatable :: type
contains
procedure, pass(fd), public :: open_file
end type FileHandler
abstract interface
subroutine File_open_file( fd )
import FileHandler
class(FileHandler), intent(inout) :: fd
end subroutine
end interface
CONTAINS
subroutine write_output()
IMPLICIT NONE
type(FileHandler) :: FileH
!-------------------------------------------------------------------------
print*, 'write_output: start.'
allocate(TypeB :: FileH%type)
allocate( FormatA :: FileH%type%format)
call FileH%open_file()
print*, 'write_output: end.'
end subroutine write_output
subroutine open_file( fd )
implicit none
class(FileHandler), intent(inout) :: fd
!-------------------------------------------------------------------------
print *, 'open_file: start'
call fd%type%format%open_files(fd)
print *, 'open_file: end'
end subroutine open_file
subroutine open_fileA( fd )
implicit none
class(FileHandler), intent(inout) :: fd
!-------------------------------------------------------------------------
print *, 'open_fileA: start'
!print*, 'job done'
print *, 'open_fileA: end'
end subroutine open_fileA
end module modu
PROGRAM main_prog
USE modu
print*, "Start main"
call write_output()
print*, "End main"
END PROGRAM main_prog
Therefore the command pgfortran -c test.f90 && pgfortran -o main_test test.o && ./main_test returns me:
Start main
write_output: start.
open_file: start
Segmentation fault (core dumped)
While it run as expected with gfortran or ifort. Otherwise I also tested this code with the option -Mnollvm of the PGI compiler, and it yields the same segmentation fault.
Of course in this simple example I could remove the intermediate object TypeFile, which remove the segmentation fault problem ; but I really need it in some bigger project.
So am I missing something ? or is it a bug of the PGI compiler ?
Related
I would like to create a parametrized derived type inside a procedure and operate on the type's member. The following code works and writes out 4 and 8, as expected.
module mod1
implicit none
type :: pdt(n)
integer, len :: n
integer :: a(n), b(n)
end type
end module mod1
program main
use mod1
implicit none
type(pdt(4)) :: aa
print *, aa%n
print *, func(4)
contains
integer function func(n) result(m)
integer :: n
type(pdt(n)) :: pdttest
m = 2*pdttest%n
end function
end program
The problem arises when I place the procedure func in a separate module, in which case pdttest%n is uninitialized. Compiling using gfortran 11.2.0 with the flag -Wall returns:
Warning: ‘pdttest.n’ is used uninitialized [-Wuninitialized]
What could be the cause of this?
module mod2
use mod1
implicit none
contains
integer function func(n) result(m)
integer :: n
type(pdt(n)) :: pdttest
m = 2*pdttest%n
end function
end module
I am working on a Fortran code. And I have to deal with many different type of output file. So to manage all of them, I use type objects.
Until now, I have compiled my code with gfortran on linux and windows (and ifort on linux) ; and it works as expected.
Because, I want in a close future to integrate GPU parallel computing to my code with OpenACC, I have to be able to compile it with pgfortran (the PGI compiler for Fortran).
Here arrives my problem, the compilation (with pgfortran 18-4-0 on windows) returns me no warning, but at the execute the code crashes with a strange error: [Exit 3221225477] test.exe.
Therefore, I tried to isolate the problem, in order to solve it. I finally get the following MWE:
MODULE VTK_IO
implicit none
type, abstract :: FormatVTK
contains
procedure(VTK_open_file),nopass, deferred :: open_file_VTK
procedure(VTK_close_file),nopass, deferred :: close_file_VTK
end type FormatVTK
type, extends(FormatVTK) :: FormatAscii
contains
procedure, nopass :: open_file_VTK => open_file_ascii
procedure, nopass :: close_file_VTK => close_file_ascii
end type FormatAscii
type, public :: VTKfileHandler
integer :: unit
class(FormatVTK), allocatable :: type
end type VTKfileHandler
abstract interface
subroutine VTK_open_file( fd )
import VTKfileHandler
class(VTKfileHandler), intent(inout) :: fd
end subroutine
subroutine VTK_close_file(fd)
import VTKfileHandler
class(VTKfileHandler), intent(in) :: fd
end subroutine
end interface
contains
subroutine open_file_ascii( fd )
implicit none
class(VTKfileHandler), intent(inout) :: fd
character(len=80) :: f
!-------------------------------------------------------------------------
write(unit=*, fmt=*) 'open_file_ascii: start'
! stop 6969
f='test_file.txt'
open(newunit = fd%unit, &
file = trim(adjustl(f)), &
form = 'FORMATTED', & ! FORMATTED
access = 'STREAM', & ! SEQUENTIAL
action = 'WRITE', &
status = 'REPLACE')
write(unit=fd%unit,fmt='(100A)') "# vtk DataFile Version "
write(unit=*, fmt=*) 'open_file_ascii: end'
end subroutine open_file_ascii
subroutine close_file_ascii(fd)
implicit none
class(VTKfileHandler), intent(in) :: fd
!-------------------------------------------------------------------------
close(unit=fd%unit)
write(unit=*, fmt=*) 'close_file_ascii: done'
end subroutine close_file_ascii
end module vtk_IO
PROGRAM Test_open
USE VTK_IO
IMPLICIT NONE
type :: OutputFile
class (VTKfileHandler), allocatable :: VTKfile
end type OutputFile
type (OutputFile) :: OutsFiles
!----------------------------------------------------------------------------
print*, 'START: Test_open'
Print*,'initialise_outputs: start'
allocate(VTKfileHandler :: OutsFiles%VTKfile )
allocate(FormatAscii :: OutsFiles%VTKfile%type)
Print*,'initialise_outputs: end'
call OutsFiles%VTKfile%type%open_file_VTK(OutsFiles%VTKfile)
call OutsFiles%VTKfile%type%close_file_VTK(OutsFiles%VTKfile)
print*, 'END: Test_open'
END PROGRAM Test_open
It seems like the type-bound procedure open_file_VTK is not targetting the procedure open_file_ascii. I think that the compiler get lost with the type-bounded procedure. For example, if I remove the OutsFiles and use directly a VTKfile in the main, it works. But, of course, I need this embedding type OutputFile, in my big code ; otherwise it would be too easy.
So is it a bug from the compiler ? Or can I do something to solve this problem ?
When we compile (gfortran 5.3 or 7.2) and run the following code, line 9 of the main.f03 ends up in a subroutine that is never called. Can anyone explain why?
main.f03:
program main
use minimalisticcase
implicit none
type(DataStructure) :: data_structure
type(DataLogger) :: data_logger
call data_structure%init()
call data_logger%init(data_structure)
end program
minimalisticcase.f03:
module minimalisticcase
implicit none
type, public :: DataStructure
integer :: i
contains
procedure, pass :: init => init_data_structure
procedure, pass :: a => beginning_of_alphabet
end type
type, public :: DataLogger
type(DataStructure), pointer :: data_structure
contains
procedure, pass :: init => init_data_logger
procedure, pass :: do_something => do_something
end type
contains
subroutine init_data_structure(self)
implicit none
class(DataStructure), intent(inout) :: self
write(*,*) 'init_data_structure'
end subroutine
subroutine beginning_of_alphabet(self)
implicit none
class(DataStructure), intent(inout) :: self
write(*,*) 'beginning_of_alphabet'
end subroutine
subroutine init_data_logger(self, data_structure)
implicit none
class(DataLogger), intent(inout) :: self
class(DataStructure), target :: data_structure
write(*,*) 'init_data_logger'
self%data_structure => data_structure
call self%do_something()
end subroutine
subroutine do_something(self)
implicit none
class(DataLogger), intent(inout) :: self
write(*,*) 'do_something'
end subroutine
end module
On line 40 of 'minimalisticcase.f03' we call 'do_something' of the DataLogger. But instead the 'beginning_of_alphabet' subroutin of DataStructure is executed!
Apparently one can fix this by changing line 13 in 'minimalisticcase.f03' from type(DataStructure), pointer :: data_structure to class(DataStructure), pointer :: data_structure.
But why?
This is a bug in gfortran. I posted it on Bugzilla as https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82312. The error is now fixed on the GCC trunk.
A temporary workaround is to encase the pointer assignment in a select type, thusly:
select type (data_structure)
type is (DataStructure)
self%data_structure => data_structure
end select
I'm trying to put together a minimal example for performing user-defined derived type input output in Fortran using ifort compiler version 15. The code posted below is able to read and write accordingly, however after "read" is done executing and while control is being returned to the main program the following error occurs:
(61586,0x7fff7e4dd300) malloc: *** error for object 0x10fa7bac4: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
The UDDTIO routines are called in the program as:
module mod_test
implicit none
type, public :: class_test
integer :: foo
contains
procedure, private :: write_test
procedure, private :: read_test
generic :: write(formatted) => write_test
generic :: read(formatted) => read_test
end type class_test
contains
subroutine write_test(dtv, unit, iotype, v_list, iostat, iomsg)
!
implicit none
!
class(class_test), intent(in) :: dtv
integer , intent(in) :: unit
character(*), intent(in) :: iotype
integer , intent(in) :: v_list(:)
integer , intent(out) :: iostat
character(*), intent(inout) :: iomsg
!
iostat = 0
!
write(unit,'(a,/)') '<foo>'
write(unit,*) dtv%foo
write(unit,'(/)')
write(unit,'(a,/)') '</foo>'
!
end subroutine write_test
subroutine read_test(dtv, unit, iotype, v_list, iostat, iomsg)
!
implicit none
!
class(class_test), intent(inout) :: dtv
integer , intent(in) :: unit
character(*), intent(in) :: iotype
integer , intent(in) :: v_list(:)
integer , intent(out) :: iostat
character(*), intent(inout) :: iomsg
!
read(unit,'(/)')
read(unit,*) dtv%foo
read(unit,'(/)')
read(unit,'(/)')
write(*,*) 'z'
end subroutine read_test
end module mod_test
program main
use mod_test
implicit none
type(class_test) :: test
test%foo = 5
write(*,*) 'writing'
open(unit=1, file='write.out', status='replace', action='write')
write(unit=1,fmt=*) test
close(unit=1)
write(*,*) 'reading'
open(unit=1, file='write.out', status='old', action='read')
read(unit=1,fmt=*) test
close(unit=1)
write(*,*) 'end'
end program main
The problem seems to be with the line break statements '(/)'.
Adding iostat=-1 to the read routine seems "solve" the problem. But why?
UDDTIO procedures are required to define the iostat dummy argument, so that the compiler's runtime can test for error and take the appropriate action.
Note that UDDTIO is a relatively recently implemented feature for that compiler. You need to be using the latest possible compiler version.
If I define the iostat dummy argument appropriately in the read and write UDDTIO procedures, your code runs for me with the current 17.0 beta.
Further UDDTIO issues should be fixed in the initial release of 17.0, which can't be too far away.
I am getting a compiler error with the gfortran v4.9.0 compiler when using the private statement within a derived type class that is used to form a polymorphic object. Conversely, ifort v14.0.2 does compile this code successfully and the executable runs without error. The example source code below results in the following error message from gfortran:
ch2605.poly.f90:58.2:
s %x = shape_type(3)
1
Error: Assignment to an allocatable polymorphic variable at (1) is not
yet supported
If the private statement is commented out and the entire shape_module attributes/methods are made public, then gfortran compiles the code successfully. My 2 questions are:
1) Is the gfortran error message above correct in this case?
2) Is there anything I should do differently when attempting to make the contents of the base derived type shape_type private?
Note: I have adapted this example source code from ch2605_2.f90 on the fortranplus website.
! Test to demonstrate problem private attributesin polymorphic
! derived type using gfortan v4.9.0 (works OK in ifort v14.0.2)
module shape_module
implicit none
private ! *** Commenting out this statement works with gfortran v4.9.0
type shape_type
integer :: n_
character(len=2), allocatable, dimension(:) :: cname_
contains
procedure, pass(this) :: get_size
end type shape_type
interface shape_type
module procedure shape_type_constructor
end interface
interface assignment (=)
module procedure generic_shape_assign
end interface
public :: shape_type, generic_shape_assign
public :: shape_type_constructor, get_size ! *** Not even this works.
contains
type (shape_type) function shape_type_constructor(n)
implicit none
integer, intent (in) :: n
shape_type_constructor%n_ = n
allocate ( shape_type_constructor%cname_(n) )
end function shape_type_constructor
integer function get_size(this)
implicit none
class (shape_type), intent (in) :: this
get_size = size(this%cname_)
end function get_size
subroutine generic_shape_assign(lhs,rhs)
implicit none
class (shape_type), intent (out), allocatable :: lhs
class (shape_type), intent (in) :: rhs
allocate (lhs,source=rhs)
end subroutine generic_shape_assign
end module shape_module
module shape_wrapper_module
use shape_module
type shape_wrapper
class (shape_type), allocatable :: x
end type shape_wrapper
end module shape_wrapper_module
program ch2605_mod
use shape_module
use shape_wrapper_module
implicit none
type (shape_wrapper) :: s
s %x = shape_type(3)
print *, 'size = ', s%x%get_size()
end program ch2605_mod