The code I have written below compiles fine using GFORTRAN, however when I run the executable, the terminal window returns...
Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
Backtrace for this error:
#0 0x7FC1D0F93697
#1 0x7FC1D0F93CDE
#2 0x7FC1D048E3EF
#3 0x7FC1D05AF392
#4 0x7FC1D1058360
#5 0x400CBA in MAIN__ at TRANS2DATUM.f90:?
Segmentation fault (core dumped)
The code is as follows
PROGRAM TRANSLATE
IMPLICIT NONE
REAL, ALLOCATABLE :: X(:), Y(:), Z(:)
INTEGER, ALLOCATABLE :: NID(:)
REAL MINVALUE
INTEGER i, NUMA
OPEN(1,FILE='NODE_original.dat',STATUS='OLD')
OPEN(2,FILE='NODE_trans.dat',STATUS='NEW')
10 READ(1,*,END=100)NID(i), X(i), Y(i), Z(i)
i=i+1
GOTO 10
100 CONTINUE
NUMA=i
ALLOCATE (NID(NUMA),X(NUMA),Y(NUMA),Z(NUMA))
! Find the z value that should be zero
MINVALUE=Z(1)
DO i = 1, NUMA
If ( i .EQ. 1) GOTO 11
If (Z(i) .LE. Z(i-1)) THEN
MINVALUE=Z(i)
Else
END IF
11 CONTINUE
END DO
WRITE(*,*) "MINIMUM Z DIMENSION IS: ",MINVALUE
IF (MINVALUE .EQ. 0) GOTO 12
WRITE(2,*)"*NODES, NSET=NBRICK"
DO i = 1, NUMA
Z(i) = Z(i) - MINVALUE
WRITE(2, 1002) NID(i), X(i), Y(i), Z(i)
END DO
1002 FORMAT(I10,3(",",F12.5))
12 WRITE(*,*) "ERROR: MINIUMUM VALUE ALREADY ZERO NO TRANSLATION REQUIRED"
STOP
END PROGRAM
When I use this command as recommended in one of the comments below:
gfortran -o -g -Wall -fcheck=all T2DATUM TRANS2DATUM.f90
I get the following
T2DATUM: In function `_fini':
(.fini+0x0): multiple definition of `_fini'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crti.o:(.fini+0x0): first defined here
T2DATUM: In function `data_start':
(.data+0x0): multiple definition of `__data_start'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o:(.data+0x0): first defined here
T2DATUM:(.rodata+0x8): multiple definition of `__dso_handle'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbegin.o:(.rodata+0x0): first defined here
T2DATUM:(.rodata+0x0): multiple definition of `_IO_stdin_used'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o:(.rodata.cst4+0x0): first defined here
T2DATUM: In function `_start':
(.text+0x0): multiple definition of `_start'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o:(.text+0x0): first defined here
T2DATUM: In function `_init':
(.init+0x0): multiple definition of `_init'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crti.o:(.init+0x0): first defined here
/tmp/ccbWNZCJ.o: In function `main':
TRANS2DATUM.f90:(.text+0x1205): multiple definition of `main'
T2DATUM:(.text+0xc43): first defined here
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtend.o:(.tm_clone_table+0x0): multiple definition of `__TMC_END__'
T2DATUM:(.data+0x8): first defined here
/usr/bin/ld: error in T2DATUM(.eh_frame); no .eh_frame_hdr table will be created.
collect2: error: ld returned 1 exit status
But I have no idea what any of this means
What is causing this issue?
I am thinking it is to do with the allocatable arrays? I was hoping to use dynamic arrays because I don't have to recompile everytime I need to change the size of the arrays. Is this the best way of doing this?
Thanks for any help.
This is a working version with small modifications:
NODE_original.dat
1 2. 3. 4.
5 6. 7. 8.
9 10. 11. 12.
13 14. 15. 16.
17 18. 19. 20.
test.f90
PROGRAM TRANSLATE
IMPLICIT NONE
REAL, ALLOCATABLE :: X(:), Y(:), Z(:)
INTEGER, ALLOCATABLE :: NID(:)
REAL MINVALUE
INTEGER i, NUMA
! Declare vars used for temporarily receiving
! the values read from the file
REAL X_, Y_, Z_
INTEGER :: NID_
OPEN(1,FILE='NODE_original.dat',STATUS='OLD')
OPEN(2,FILE='NODE_trans.dat',STATUS='NEW')
! i was not defined to start as zero as it should
i=0
10 READ(1,*,END=100)NID_, X_, Y_, Z_
i=i+1
GOTO 10
100 CONTINUE
NUMA=i
! Values were previously read but not stored.
! NUMA is used to allocate the arrays with the
! proper dimensions.
ALLOCATE (NID(NUMA),X(NUMA),Y(NUMA),Z(NUMA))
! Cursor of file 1 is rewind to the beginning of
! the file
REWIND(1)
! Read is executed for all lines with i being
! incremented by 1 every reading up to i=NUMA.
! Values are stored in the arrays at index i
! and can now be used as intended.
READ(1,*)(NID(i), X(i), Y(i), Z(i), i=1,NUMA)
! Find the z value that should be zero
MINVALUE=Z(1)
DO i = 1, NUMA
If ( i .EQ. 1) GOTO 11
If (Z(i) .LE. Z(i-1)) THEN
MINVALUE=Z(i)
Else
END IF
11 CONTINUE
END DO
WRITE(*,*) "MINIMUM Z DIMENSION IS: ",MINVALUE
IF (MINVALUE .EQ. 0) GOTO 12
WRITE(2,*)"*NODES, NSET=NBRICK"
DO i = 1, NUMA
Z(i) = Z(i) - MINVALUE
WRITE(2, 1002) NID(i), X(i), Y(i), Z(i)
END DO
1002 FORMAT(I10,3(",",F12.5))
12 WRITE(*,*) "ERROR: MINIUMUM VALUE ALREADY ZERO NO TRANSLATION REQUIRED"
STOP
END PROGRAM
Output:
:~$ gfortran --version
GNU Fortran (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
:~$ gfortran stack.f90
:~$ ./a.out
MINIMUM Z DIMENSION IS: 4.00000000
ERROR: MINIUMUM VALUE ALREADY ZERO NO TRANSLATION REQUIRED
Related
I am trying to avoid memory allocation and local copy in my code. Below is a small example :
module test
implicit none
public
integer, parameter :: nb = 1000
type :: info
integer n(nb)
double precision d(nb)
end type info
type(info), save :: abc
type(info), target, save :: def
contains
subroutine test_copy(inf)
implicit none
type(info), optional :: inf
type(info) :: local
if (present(inf)) then
local = inf
else
local = abc
endif
local%n = 1
local%d = 1.d0
end subroutine test_copy
subroutine test_assoc(inf)
implicit none
type(info), target, optional :: inf
type(info), pointer :: local
if (present(inf)) then
local => inf
else
local => def
endif
local%n = 1
local%d = 1.d0
end subroutine test_assoc
end module test
program run
use test
use caliper_mod
implicit none
type(ConfigManager), save :: mgr
abc%n = 0
abc%d = 0.d0
def%n = 0
def%d = 0.d0
! Init caliper profiling
mgr = ConfigManager_new()
call mgr%add("runtime-report(mem.highwatermark,output=stdout)")
call mgr%start
! Call subroutine with copy
call cali_begin_region("test_copy")
call test_copy()
call cali_end_region("test_copy")
! Call subroutine with pointer
call cali_begin_region("test_assoc")
call test_assoc()
call cali_end_region("test_assoc")
! End caliper profiling
call mgr%flush()
call mgr%stop()
call mgr%delete()
end program run
As far as i understand, the subroutine test_copy should produce a local copy while the subroutine test_assoc should only assign a pointer to some existing object. However, memory profiling with caliper leads to :
$ ./a.out
Path Min time/rank Max time/rank Avg time/rank Time % Allocated MB
test_assoc 0.000026 0.000026 0.000026 0.493827 0.000021
test_copy 0.000120 0.000120 0.000120 2.279202 0.000019
What looks odd is that Caliper shows the exact same amount of memory allocated whatever the value of the parameter nb. Am I using the right tool the right way to track memory allocation and local copy ?
Test performed with gfortran 11.2.0 and Caliper 2.8.0.
The local object is just a simple small scalar, albeit containing an array component, and will be very likely placed on the stack.
A stack is a pre-allocated part of memory of fixed size. Stack "allocation" is actually just a change of value of the stack pointer which is just one integer value. No actual memory allocation from the operating system takes place during stack allocation. There will be no change in the memory the process occupies.
I'm interesting in testing some of the limits of Gforth and would like to have it execute arbitrary code that I "hand compile" into allocated memory. Here is my attempt.
100 cells allocate throw constant &mem
\ store at &mem: docol: . EXIT
docol: &mem !
comp' . &mem 1 cells + ! drop \ drop "execution token"
comp' EXIT &mem 2 cells + ! drop
42 \ something to print
&mem execute
Unfortunately this fails with:
in file included from *OS command line*:-1
notes/execute.fs:8: Invalid memory address
&mem >>>execute<<<
Backtrace:
$7EFC61175B28 execute
I have to use comp' instead of ', because it doesn't work for getting the xt of EXIT.
I would have thought this should work, unless Gforth doesn't operate in any way like JonesForth did where docol: starts executing the xt's next to it.
Is this possible in either Gforth or ANS forth in general?
You can execute an arbitrary list of xt, but you have to use your own word to execute this list, by applying execute to each xt from the list.
By the current standard, a standard program cannot compile arbitrary code into allocated memory. The program may only compile into the code space of the dictionary, and in the frame of the current definition (i.e., that is not yet completed). Compilation can be performed via compile, ( xt -- ) or postpone ( i*x "name" -- j*x ) words. Also the words literal, 2literal, sliteral, fliteral (or their counterparts lit,, 2lit,, slit,, flit,) can be used to compile literals.
In Gforth you can also compile into another dictionary ("section"), that can be allocated using word extra-section ( size "name" -- ).
10000 extra-section execute-in-my-section
\ execute-in-my-section ( i*x xt -- j*x )
unused cr . \ free space in the default dictionary
[:
unused cr . \ free space in the current section
:noname
postpone .
postpone ;
( xt-new )
unused cr . \ free space after compile the new definition
;] execute-in-my-section ( xt-new )
\ test
123 swap execute
See also section.fs source, and Sections paper by Anton Ertl, 2016.
Problem (Tested on Lua 5.3 and 5.4):
a = -9223372036854775807 - 1 ==> -9223372036854775808 (lua_integer)
b = -9223372036854775808 ==> -9.2233720368548e+018 (lua_number)
Question:
Is it possible to get "-9223372036854775808" without modify "luaconf.h" or write "-9223372036854775807 - 1"?
When you write b = -9223372036854775808 in your program, the Lua parser treats this as "apply negation operator to positive integer constant", but positive constant is beyond integer range, so it's treated as float, and negation is applied to the float number, and the final result is float.
There are two solutions to get minimal integer:
Bitwise operators convert floats to integers (bitwise OR has lower priority then negation):
b = -9223372036854775808|0
Use the special constant from math library:
b = math.mininteger
P.S.
Please note that additional OR in the expression b = -9223372036854775808|0 does not make your program slower. Actually, all calculations (negation and OR) are done at compile time, and the bytecode contains only the final constant you need:
$ luac53 -l -l -p -
b = -9223372036854775808|0
main <stdin:0,0> (2 instructions at 0x244f780)
0+ params, 2 slots, 1 upvalue, 0 locals, 2 constants, 0 functions
1 [1] SETTABUP 0 -1 -2 ; _ENV "b" -9223372036854775808
2 [1] RETURN 0 1
constants (2) for 0x244f780:
1 "b"
2 -9223372036854775808
locals (0) for 0x244f780:
upvalues (1) for 0x244f780:
0 _ENV 1 0
I have a simple Fortran code, and I am getting an error that I cannot find a solution to. Does anyone know how to fix this?
subroutine sort(A,A_done,N,P)
! Sort a real array by algebraically increasing value and return the permutation that
! rearranges the array
implicit none
Integer N, TEMP1, K, L, P(N), TEMP2
real(8), dimension(:) :: A_done
real(8), dimension(:) :: A
DO K=1, N-1
DO L=K+1, N
if A(K)>A(L)
TEMP1=A(K)
TEMP2=P(K)
A(K)=A(L)
P(K)=P(L)
A(L)=TEMP1
P(L)=TEMP2
end if
END DO
END DO
A_done=A
RETURN
END
gfortran -Wall -Werror -fbounds-check -w -L -lm -o Simulation readinput.for noutfile.for mean.for covariance.for correlation.for rperm.for simmain.for sort.for
In file sort.for:13
if A(K)>A(L)
1
Error: Unclassifiable statement at (1)
In file sort.for:20
end if
1
Error: Expecting END DO statement at (1)
make: * [Simulation] Error 1
Thanks for the help
You have forgotten a pair of parentheses and a "then":
At if A(K)>A(L) you must type if (A(K)>A(L)) then
Other than that, your code has multiple issues:
At TEMP1=A(K) and similar expressions, you pass a real(8) value to an integer variable
I don't understand what the P variable does (could you describe please?), but you also mix real(8) and integer there.
You MUST specify the dimension of the arrays in the subroutine. (I think there is a way not doing so by using modules)
Keep in mind that you change A and then you copy it to A_done. Why to do so? You lose your original values and consume more memory.
I have made some corrections that you may want to keep, you may make more. This code compiles and runs well.
Program test
implicit none
integer N
real(8), allocatable :: A(:), A_done(:), P(:)
N=5
Allocate (A(N), A_done(N), P(N))
A=(/5,3,6,1,9/)
call sort(A, A_done, N, P)
Write (*,*) A_done
End
subroutine sort(A,A_done,N,P)
! Sort a real array by algebraically increasing value and return the permutation that
! rearranges the array
implicit none
Integer N, K, L
real(8), dimension(N) :: A, A_done, P
real(8) :: TEMP1, TEMP2
DO K=1, N-1
DO L=K+1, N
if (A(K)>A(L)) then
TEMP1=A(K)
TEMP2=P(K)
A(K)=A(L)
P(K)=P(L)
A(L)=TEMP1
P(L)=TEMP2
end if
END DO
END DO
A_done=A
RETURN
END
I have many text files of this format
....
<snip>
'FOP' 0.19 1 24 1 25 7 8 /
'FOP' 0.18 1 24 1 25 9 11 /
/
TURX
560231
300244
70029
200250
645257
800191
900333
600334
770291
300335
220287
110262 /
SUBTRACT
'TURX' 'TURY'/
</snip>
......
where the portions I snipped off contain other various data in various formats. The file format is inconsistent (machine generated), the only thing one is assured of is the keyword TURX which may appear more than once. If it appears alone on one line, then the next few lines will contain numbers that I need to fetch into an array. The last number will have a space then a forward slash (/). I can then use this array in other operations afterwards.
How do I "search" or parse a file of unknown format in fortran, and how do I get a loop to fetch the rest of the data, please? I am really new to this and I HAVE to use fortran. Thanks.
Fortran 95 / 2003 have a lot of string and file handling features that make this easier.
For example, this code fragment to process a file of unknown length:
use iso_fortran_env
character (len=100) :: line
integer :: ReadCode
ReadLoop: do
read (75, '(A)', iostat=ReadCode ) line
if ( ReadCode /= 0 ) then
if ( ReadCode == iostat_end ) then
exit ReadLoop
else
write ( *, '( / "Error reading file: ", I0 )' ) ReadCode
stop
end if
end if
! code to process the line ....
end do ReadLoop
Then the "process the line" code can contain several sections depending on a logical variable "Have_TURX". If Have_TRUX is false you are "seeking" ... test whether the line contains "TURX". You could use a plain "==" if TURX is always at the start of the string, or for more generality you could use the intrinsic function "index" to test whether the string "line" contains TURX.
Once the program is in the mode Have_TRUX is true, then you use "internal I/O" to read the numeric value from the string. Since the integers have varying lengths and are left-justified, the easiest way is to use "list-directed I/O": combining these:
read (line, *) integer_variable
Then you could use the intrinsic function "index" again to test whether the string also contains a slash, in which case you change Have_TRUX to false and end reading mode.
If you need to put the numbers into an array, it might be necessary to read the file twice, or to backspace the file, because you will have to allocate the array, and you can't do that until you know the size of the array. Or you could pop the numbers into a linked list, then when you hit the slash allocate the array and fill it from the linked list. Or if there is a known maximum number of values you could use a temporary array, then transfer the numbers to an allocatable output array. This is assuming that you want the output argument of the subroutine be an allocatable array of the correct length, and the it returns one group of numbers per call:
integer, dimension (:), allocatable, intent (out) :: numbers
allocate (numbers (1: HowMany) )
P.S. There is a brief summary of the language features at http://en.wikipedia.org/wiki/Fortran_95_language_features and the gfortran manual has a summary of the intrinsic procedures, from which you can see what built in functions are available for string handling.
I'll give you a nudge in the right direction so that you can finish your project.
Some basics:
Do/While as you'll need some sort of loop
structure to loop through the file
and then over the numbers. There's
no for loop in Fortran, so use this
type.
Read
to read the strings.
To start you need something like this:
program readlines
implicit none
character (len=30) :: rdline
integer,dimension(1000) :: array
! This sets up a character array with 30 positions and an integer array with 1000
!
open(18,file='fileread.txt')
do
read(18,*) rdline
if (trim(rdline).eq.'TURX') exit !loop until the trimmed off portion matches TURX
end do
See this thread for way to turn your strings into integers.
Final edit: Looks like MSB has got most of what I just found out. The iostat argument of the read is the key to it. See this site for a sample program.
Here was my final way around it.
PROGRAM fetchnumbers
implicit none
character (len=50) ::line, numdata
logical ::is_numeric
integer ::I,iost,iost2,counter=0,number
integer, parameter :: long = selected_int_kind(10)
integer, dimension(1000)::numbers !Can the number of numbers be up to 1000?
open(20,file='inputfile.txt') !assuming file is in the same location as program
ReadLoop: do
read(20,*,iostat=iost) line !read data line by line
if (iost .LT. 0) exit !end of file reached before TURX was found
if (len_trim(line)==0) cycle ReadLoop !ignore empty lines
if (index(line, 'TURX').EQ.1) then !prepare to begin capturing
GetNumbers: do
read(20, *,iostat=iost2)numdata !read in the numbers one by one
if (.NOT.is_numeric(numdata)) exit !no more numbers to read
if (iost2 .LT. 0) exit !end of file reached while fetching numbers
read (numdata,*) number !read string value into a number
counter = counter + 1
Storeloop: do I =1,counter
if (I<counter) cycle StoreLoop
numbers(counter)=number !storing data into array
end do StoreLoop
end do GetNumbers
end if
end do ReadLoop
write(*,*) "Numbers are:"
do I=1,counter
write(*,'(I14)') numbers(I)
end do
END PROGRAM fetchnumbers
FUNCTION is_numeric(string)
IMPLICIT NONE
CHARACTER(len=*), INTENT(IN) :: string
LOGICAL :: is_numeric
REAL :: x
INTEGER :: e
is_numeric = .FALSE.
READ(string,*,IOSTAT=e) x
IF (e == 0) is_numeric = .TRUE.
END FUNCTION is_numeric