My IDE is Visual Studio 2010 with integrated Intel Fortran compiler. The version of compiler is: Intel Parallel Studio XE 2011.
I am not experienced programer in Fortran so I need a little help about using pointers in reading data from .txt files. This is my example code:
Module Derived_type
implicit none
Type , public :: Something
private
Real :: Somth_1
Integer :: Somth_2
contains
procedure , public :: read_input => read_data_input
procedure , public :: t_Somth_1 => t_data_Somth_1
procedure , public :: t_Somth_2 => t_data_Somth_2
End Type Something
private :: read_data_input
private :: t_data_Somth_1 , t_data_Somth_2
contains
Subroutine read_data_input( This , Un_r )
Class( Something ) :: This
Integer , intent( in ) :: Un_r
Read ( Un_r , * , Err = 100 ) This%Somth_1
Read ( Un_r , * , Err = 101 ) This%Somth_2
Return
100 Stop ( "Read format error - 100 !!!" )
101 Stop ( "Read format error - 101 !!!" )
End Subroutine read_data_input
Function t_data_Somth_1 ( This ) result( data_Somth_1 )
Class( Something ) :: This
Real :: data_Somth_1
data_Somth_1 = This%Somth_1
End Function t_data_Somth_1
Function t_data_Somth_2 ( This ) result( data_Somth_2 )
Class( Something ) :: This
Integer :: data_Somth_2
data_Somth_2 = This%Somth_2
End Function t_data_Somth_2
End Module Derived_type
Program Memory_leaking
Use , non_intrinsic :: Derived_type
Implicit none
Integer :: i , alloc_err , dealloc_err
Integer , parameter :: N_snv = 3
Character( 256 ) :: Name
Character(*),parameter :: a00 = '("Input_",i1,".txt")'
Class( Something ) , pointer :: Po_Something
Type( Something ) , allocatable , target :: Tar_Something(:)
! Memory allocation
allocate ( Po_Something , Stat = alloc_err )
If ( alloc_err .ne. 0 ) Stop ( "Allocation wrong - Po_Something !!!")
If ( .not. allocated ( Tar_Something ) ) allocate( Tar_Something( N_snv ) , stat = alloc_err )
If ( alloc_err .ne. 0 ) Stop ( "Allocation wrong - Tar_Something !!!")
Do i = 1 , N_snv
Po_Something => Tar_Something(i)
Write( Name , a00 ) i
Open( 15 , File = Name , Status = 'Unknown' , Action = 'Read' )
Call Po_Something%read_input( 15 )
Close( 15 , Status = 'Keep' )
Write(*,*) Po_Something%t_Somth_1() , Po_Something%t_Somth_2()
End Do
! Memory deallocation
deallocate ( Po_Something , Stat = dealloc_err )
If ( dealloc_err .ne. 0 ) Stop ( "deAllocation wrong - Po_Something !!!")
If ( allocated ( Tar_Something ) ) deallocate( Tar_Something, stat = dealloc_err )
If ( dealloc_err .ne. 0 ) Stop ( "deAllocation wrong - Tar_Something !!!")
End program Memory_leaking
I have a one array which is derived type and I want to read data from .txt file for every single array using same pointer, just like in my example code.
I there need for breaking conection beatwean pointer and target in afther do loop execution was done?
Is there memory leaking in this case?
Yes, you have a memory leak.
allocate ( Po_Something , Stat = alloc_err )
Here you allocated, manually, storage for your pointer variable and pointed to its memory address.
Po_Something => Tar_Something(i)
Just after, you changed the poitee to another storage (the allocatable variable) and left behind the storage you allocated before. After this pointer association, there is no reference left anymore pointing to the address you allocated manually. The program won't be able to deallocate it when it reaches the end.
As you are not using the storage of the first allocation, the solution here is just not doing it. The pointer will point to memory already allocated in the loop.
Allocatable variables are deallocated automatically (in modern Fortran), but any memory you allocated manually for a pointer variable need to be manually deallocated before you change the its target.
Check my other answer about when manual deallocation is needed for reference.
When is array deallocating necessary?
(better than that, download a copy of the Fortran Standard for reference here https://wg5-fortran.org )
Related
I have a function of some variables, which will yield an array consisted of both negative and positive values (Real). But since only positive values are physically meaningful to me, I want to set all negative values inside the array to be zero.
I have provided my code related to this function below:
The reason I declare a temporary variable 'res' is that I try to build in an IF-ELSE in the position I marked in code as follows:
If (res >= 0) Then
result = res
Else
result = 0
End If
But the error says a scalar-valued expression for S_A if required here.
If instead of res we use res(il,ir) is used,
If (res(il,ir) >= 0) Then
result(il,ir) = res(il,ir)
Else
result = 0
End If
the error says error #6351: The number of subscripts is incorrect.
Is there any way to implement this idea?
Function somefunction(x,y,il,ir) Result(result)
!! ---- begin of declaration ---------------------------
Implicit None
!! boundary indices
Integer, Intent ( in ) :: il,ir
!! the vars
Real ( kind = rk ), Intent ( in ), Dimension ( il:ir ) :: x,y
!! the result
Real ( kind = rk ), Dimension ( il:ir ) :: result
!! temp vars
Real ( kind = rk ), Dimension ( il:ir ) :: res
!! loop index
Integer :: i
!! ---- end of declaration -----------------------------
res = x+y
SA = S_A
!!IF-ELSE!!
End Function somefunction
If you want to have an if statement element wise on an array, you should use the where statement, for example:
program min0
implicit none
real :: res(5, 5), result(5, 5)
call random_number(res)
res=res-0.5
print '(5(F5.2,X))', res
where (res>=0)
result = res
elsewhere
result = 0
end where
print *, '---------------------------------------'
print '(5(F5.2,X))', result
end program min0
I don't know why you get a subscript error, it might help if you tell us which line of the code the error occurs. But of course in the second code, you update a single element of result if res is larger than 0, but set the whole array result to 0 if it isn't. This is almost certainly not what you want.
Cheers
The function appears to take in X and Y dimensioned from (il:if)... say from (3:6), so a vector. However the index later says (il,ir) which means it is a 2 dimensional array.
WHERE seems like a good choice. Another would be a logical MASK to associate the where-positions. It makes sense is PACK and unpack are usd,
Why even say what size the vectors are?
ELEMENTAL Function somefunction(x,y) Result(Res)
!! ---- begin of declaration ---------------------------
Implicit None
Real ( kind = rk ), Intent (IN), Dimension (:) :: x,y
!! the result
Real ( kind = rk ), Dimension ( il:ir ) :: res
!! loop index
Integer :: i
!! ---- end of declaration -----------------------------
res = x+y
WHERE res <= 0
Res = 0
ENDWHERE
!!IF-ELSE!!
End Function somefunction
Then on the calling side... call the function over the range of undecided you want.
Z(1:5) = somefunction(X(1:5),Y(1:5))
This is my simple( test ) code:
MODULE TEST_MODULE
USE, INTRINSIC :: ISO_C_BINDING
IMPLICIT NONE
INTEGER, PARAMETER :: IP = C_INT
INTEGER, PARAMETER :: LP = C_BOOL
INTEGER, PARAMETER :: CP = C_CHAR
INTEGER( IP ), PARAMETER :: UN = 15
INTEGER( IP ) :: DATA_00, DATA_01, DATA_02
CHARACTER(*), PARAMETER :: FMTR = 'BASE\DATA_STORAGE.TXT'
CONTAINS
FUNCTION DATA_READING( ) RESULT( ERROR_TMP )
LOGICAL( LP ) :: ERROR_TMP
ERROR_TMP = .FALSE.
OPEN( UNIT = UN, FILE = FMTR, ACTION = 'READ', STATUS = 'UNKNOWN', ERR = 100 )
READ( UN, * , ERR = 101 ) DATA_00
READ( UN, * , ERR = 102 ) DATA_01
READ( UN, * , ERR = 103 ) DATA_02
CLOSE( UNIT = UN, STATUS = 'KEEP')
RETURN
100 WRITE(*,*) "ERROR - NO SUCH A FILE OR FILE LOCATION !!!"
ERROR_TMP = .TRUE.
101 WRITE(*,*) "ERROR - FMT OF READING - DATA_TMP_00 - 101 !!!"
ERROR_TMP = .TRUE.
102 WRITE(*,*) "ERROR - FMT OF READING - DATA_TMP_01 - 102 !!!"
ERROR_TMP = .TRUE.
103 WRITE(*,*) "ERROR - FMT OF READING - DATA_TMP_02 - 103 !!!"
ERROR_TMP = .TRUE.
END FUNCTION DATA_READING
END MODULE TEST_MODULE
PROGRAM TEST_CODE
USE, NON_INTRINSIC :: TEST_MODULE
IMPLICIT NONE
LOGICAL( LP ) :: GLOBAL_ERR
GLOBAL_ERR = DATA_READING()
IF ( GLOBAL_ERR ) STOP ( "ERROR - DATA READING !!!" )
PRINT *, DATA_00
PRINT *, DATA_01
PRINT *, DATA_02
END PROGRAM TEST_CODE
The DATA_STORAGE.TXT file contains:
1407
1408
1409
When I run the program, it will load the data from the specified file in the correct way - there will not be a global error message because all the data in the file is an integer type.
For example, if the changed value of the first data in 1407.23,which is real type, after the startup, the program will print on the screen all the error labels, including the one about the existence of a global error.
My question is:
How to print on the screen only the error label that belongs to the data whose entry format is not correct?
The code was tested in two IDE:
Code::Blocks 1712 GFortan 6.3.0
Visual Studio 2010 with Intel Parallel XE 2011
My IDE is Code::Blocks 17.2 with compiler GFortran 6.3.1
The all code is:
PROGRAM EES_TEST
USE , NON_INTRINSIC :: DERIVED_TYPE
IMPLICIT NONE
INTEGER :: I , ALLOC_ERR , DEALLOC_ERR
LOGICAL :: GLOBAL_ERR
CLASS ( TRONA ) , POINTER :: P_TRA
TYPE ( TRONA ) , ALLOCATABLE , TARGET :: TRAN(:)
IF ( .NOT. ALLOCATED ( TRAN ) ) ALLOCATE ( TRAN ( 2 ) , STAT = ALLOC_ERR )
IF ( ALLOC_ERR .NE. 0 ) STOP ("PROBLEM WITH MEMORY ALLOCATION - TRAN!!!")
OPEN ( UNIT = 15 , FILE = 'INPUT.TXT' , ACTION = 'READ' )
DO I = 1 , 2
P_TRA => TRAN ( I )
GLOBAL_ERR = P_TRA%UCI()
IF ( GLOBAL_ERR .EQV. .TRUE. ) STOP ("ERROR WITH READING FROM OUTPUT.TXT!")
END DO
CLOSE ( 15 )
IF ( ALLOCATED ( TRAN ) ) DEALLOCATE ( TRAN , STAT = DEALLOC_ERR )
IF ( DEALLOC_ERR .NE. 0 ) STOP ("PROBLEM WITH MEMORY DEALLOCATION - TRAN!!!")
END PROGRAM EES_TEST
MODULE DERIVED_TYPE
IMPLICIT NONE
TYPE , PUBLIC :: TRONA
PRIVATE
REAL :: Sn
REAL :: Vn
CONTAINS
PROCEDURE , PUBLIC :: UCI => UCI_POD_TRONA
PROCEDURE , PUBLIC :: TAKE_Sn => TAKE_POD_Sn
PROCEDURE , PUBLIC :: TAKE_Vn => TAKE_POD_Vn
END TYPE TRONA
PRIVATE :: UCI_POD_TRONA
PRIVATE :: TAKE_POD_Sn , TAKE_POD_Vn
CONTAINS
FUNCTION UCI_POD_TRONA ( THIS ) RESULT ( WRONG )
IMPLICIT NONE
CLASS ( TRONA ) :: THIS
LOGICAL :: WRONG
WRONG = .FALSE.
READ ( 15 , * , ERR = 100 ) THIS%Sn
READ ( 15 , * , ERR = 101 ) THIS%Vn
RETURN
100 WRITE (*,*) "WRONG FORMAT - INPUT 100!"
WRONG = .TRUE.
STOP
101 WRITE (*,*) "WRONG FORMAT - INPUT 101!"
WRONG = .TRUE.
STOP
END FUNCTION UCI_POD_TRONA
FUNCTION TAKE_POD_Sn ( THIS ) RESULT ( POD_Sn )
IMPLICIT NONE
CLASS ( TRONA ) :: THIS
REAL :: POD_Sn
POD_Sn = THIS%Sn
RETURN
END FUNCTION TAKE_POD_Sn
FUNCTION TAKE_POD_Vn ( THIS ) RESULT ( POD_Vn )
IMPLICIT NONE
CLASS ( TRONA ) :: THIS
REAL :: POD_Vn
POD_Vn = THIS%Vn
RETURN
END FUNCTION TAKE_POD_Vn
END MODULE DERIVED_TYPE
I am very new in object oriented programing in Fortran so I need an explanation about using the object pointer for calling methods from derived types. In this case I want to check is there any problem with memory leaking and if it is case is there method for checking how much memory was lost and in which line? Another thing is nullifying the derived type pointer. How to do that for this case?
Generally, unless you allocate something somewhere, you cannot have memory leaks. It is simply impossible. You can only leak something you allocate as a pointer target, nothing else.
In your code you have no allocate() for a pointer, so there cannot be any memory leaks.
For a memory leak to happen, two things must happen in sequence.
An anonymous pointer target must be allocated. That is possible only through the allocate statement
allocate(p_tra)
The pointer to the target is lost. Either it is redirected somewhere else
p_tra => somewhere_else
Or it ceases to exist, because it is a local variable of a subroutine that finishes or it is a component of a structure which is deallocated or similar...
You can always use GCC sanitizations -fssnitize=leak or valgrind to check for memory leaks.
Regarding the nulifying, just use the nulify statement or assign to null(). It is a pointer like any other.
p_tra => null()
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
Recently, I started to lean fortran programming. I have seen the following code at youtube without any error it is compiled. But I have got some errors.
I appreciate any help
program
implicit none
real, parameter :: pi=4*atan(1.0)
integer, parameter :: n = 100
real :: dimension(1:n) :: x, y
real :: a=0.0, b = 2*pi
real :: increment
integer :: i
increment = (b-a)/(real(n)-1)
x(1)=0.0
do i =2,n
x(i) = x(i-1) + increment
end do
y = sin(x)
print *, x(1:5)
print *, y(1:5)
end program
real :: dimension(1:n) :: x, y is a syntax error. Replace the first :: with a comma. You may need to give a name on the program statement.
You also have mixed-mode arithmetic in line
increment = (b-a)/(real(n)-1)
It will probably compile, and it may not even affect the program, but you should never, never have mixed-mode arithmetic in any programming language as it can cause strange, hard to find bugs.
It should look like this:
increment = (b-a)/(real(n)-1.0)
Here are the results of a working example which addresses the concerns of #High Performance Mark.
host system = (redacted)
compiler version = GCC version 5.1.0
compiler options = -fPIC -mmacosx-version-min=10.9.4 -mtune=core2 -Og -Wall -Wextra -Wconversion -Wpedantic -fmax-errors=5
execution command = ./a.out
Compare mesh points
1.57017982 1.57080817 1.57143652
1.57016802 1.57079625 1.57142460
Compare function values at these mesh points
1622.04211 -84420.7344 -1562.01758
1591.57471 13245402.0 -1591.65527
There is a bad programming practice in the demo you found: moving through the mesh by adding steps (+ increment) instead of counting them (k * increment). The problem is widespread and appears with severe consequences (https://www.ima.umn.edu/~arnold/disasters/patriot.html).
For demonstration on your code, the size of the mesh was boosted to 10K points. Also the sample function changed from cos x to tan x and we examine points near the singularity at pi/2 = 1.57079633. While the novitiate may find the discrepancies in mesh values trivial, the difference in function values is significant.
(Mesh errors can be reduced by using increments which have exact binary representation like 2^(-13) = 1 / 8192.)
The code is shown here. The compilation command is gfortran -Wall -Wextra -Wconversion -Og -pedantic -fmax-errors=5 demo.f95. The run command is ./a.out.
program demo
use iso_fortran_env
implicit none
real, parameter :: pi = acos ( -1.0 )
integer, parameter :: n = 10001
real, dimension ( 1 : n ) :: x, y, z
real :: a = 0.0, b = 2 * pi
real :: increment
integer :: k, quarter, status
character ( len = * ), parameter :: c_options = compiler_options( )
character ( len = * ), parameter :: c_version = compiler_version( )
character ( len = 255 ) :: host = " ", cmd = " "
! queries
call hostnm ( host, status )
call get_command ( cmd )
! write identifiers
write ( *, '( /, "host system = ", g0 )' ) trim ( host )
write ( *, '( "compiler version = ", g0 )' ) c_version
write ( *, '( "compiler options = ", g0 )' ) trim ( c_options )
write ( *, '( "execution command = ", g0, / )' ) trim ( cmd )
increment = ( b - a ) / ( n - 1 )
quarter = n / 4
! mesh accumulates errors
x ( 1 ) = 0.0
do k = 2, n
x ( k ) = x ( k - 1 ) + increment
end do
y = tan ( x )
print *, 'Compare mesh points'
print *, x ( quarter : quarter + 2 )
! better mesh
x ( 1 ) = 0.0
do k = 2, n
x ( k ) = ( k - 1 ) * increment
end do
z = tan ( x )
print *, x ( quarter : quarter + 2 )
print *, 'Compare function values at these mesh points'
print *, y ( quarter : quarter + 2 )
print *, z ( quarter : quarter + 2 )
end program demo
I am attempting read a large data file into Fortran it contains about 40960000 rows, I later convert it to a matrix so it would be 6400 * 6400. When I try my code using a much smaller data set it works fine. However, it tells me that there is a segmentation fault, when I use my larger dataset. I suspect that it is a memory allocation issue. Is there a way to allocate more memory or otherwise correct this problem.
program infectgrid
implicit none
integer :: i, individual, nedge,&
tempinfect_tim_err, dumnum_infalpha0, dumnum_infalpha1, alpha0counter, &
alpha1counter, obsrand, minvalshift
character (LEN = 50) :: parameterfilelabel, parameterfile, networkfilelabel, infectfilenamelabel, networkfile, infectfilename
!allocatable to allow for reading in of individuals and time periods
integer, dimension(:) , allocatable :: xcord, ycord, dummy3, recover_tim1, recover_tim2, &
recover_tim3, recover_tim4, recover_tim5, sampleadjshort, shortsamplecount, &
cov1dum, covlog, covvect1uni
character, dimension (:), allocatable :: rec
integer, dimension (:, :) , allocatable :: link
real, dimension(:) , allocatable :: alphavect
call random_seed
open(12, file = "filenamesinfection.txt", status = "old")
read(12, *) parameterfile, networkfile, infectfilename
close(12)
open(12, file = parameterfile, status = "old")
read(12, *) individualname, alpha0name, alpha1name
read(12, *) individual, alpha0, alpha1
nedge = individual*individual
allocate(rec(1:nedge))
allocate(xcord(1:nedge))
allocate(ycord(1:nedge))
allocate(dummy3(1:nedge))
allocate(sampleadjshort(1:nedge))
allocate(shortsamplecount(1:nedge))
allocate(covlog(1:nedge))
allocate(cov1dum(1:nedge))
allocate(link(1:individual, 1:individual))
link = 0
covlog = 0
print *, individual, alpha0, alpha1
print *, link(individual, individual)
print *, "test"
open(10, file = networkfile, status = "old")
print *, networkfile
print *, "test"
do i = 1, nedge
read ( 10, *) rec(i), xcord(i), ycord(i), dummy3(i), cov1dum(i), sampleadjshort(i), shortsamplecount(i)
if (dummy3(i) == 1) then
link(xcord(i), ycord(i)) = 1
end if
if (xcord(i) == ycord(i)) then
covlog(i) = 1
end if
end do
close(10)
covvect1uni = pack(cov1dum, covlog == 1)
print *, "xcord", xcord(nedge), "ycord", ycord(nedge)
print *, link(individual, individual)
print *, "test"
The file prints out the first and second "test" but does not print out the link statement nor the line starting with "xcord" and soon after gives me a segmentation fault i.e. Segmentation fault nohup ./swnetworkinfectrecoveralpha05covgeo2.out
as to compiler options, I think that I am using most of what is available: ifort -free -O2 -stand f03 -check bounds -traceback -warn all -fstack-protector -assume protect_parens -implicitnone -o swnetworkinfectrecoveralpha05covgeo2.out swnetworkinfectrecoveralpha05covgeo2.f90