2

My Fortran program compiles, but then I get a weird error called 'Bus error.'

Here is my code in its entirety. I could really use some help. Does anyone know how I can get rid of this error and get my program to work fine?

I'm trying to generate an array created via random numbers and then have the array undergo some statistics.

    PROGRAM numbersgen
IMPLICIT NONE

    !Variable declaration
    INTEGER, DIMENSION(:,:),ALLOCATABLE::numarray
    INTEGER, DIMENSION(:),ALLOCATABLE::temparray
    INTEGER:: numrolls, numexps
    INTEGER:: i=0, j=0
    REAL:: avg=0, sdv=0, variance=0, sum=0
    INTEGER:: k, min, pos, temp
    
    
    PRINT*, "Enter the number of experiments to simulate: "
    READ*, numexps
    
    PRINT*, "Enter the number of rolls per experiment: "
    READ*, numrolls
    
    ALLOCATE(numarray(numexps,numrolls))
    
    DO i=1, numexps
        CALL GenerateNum(numarray, numrolls, numexps)
        
        DO j=1, numrolls
            temparray(j)=numarray(i,j)
        END DO
    
        PRINT*, "Experiment ",i
        
        CALL Sorter(temparray, numrolls)
        CALL ComputeStats(temparray, sum, avg, variance, sdv)
        CALL PrintStats( sum, avg, variance, sdv)       
    END DO
    
    ALLOCATE(temparray(numrolls))
    
    CONTAINS
    
    SUBROUTINE GenerateNum(numarray, numrolls, numexps)
    
    INTEGER, INTENT(IN):: numrolls, numexps
    INTEGER, INTENT(OUT):: numarray(numexps, numrolls)
    REAL:: R1
    
    CALL RANDOM_SEED()
    DO i=1, numexps
        DO j=1, numrolls
    CALL RANDOM_NUMBER(R1)
    numarray(i,j)=1+INT(6*R1)
        END DO
    END DO
    
    
    
    
    !commented out for now
    !PRINT*, " "
    !PRINT*, "Unsorted"
    !DO i=1, numrolls
    !WRITE(*,23,ADVANCE="NO") temparray(i)
    !23 FORMAT (I2)
    !END DO
    !PRINT*," "
    END SUBROUTINE
    
    SUBROUTINE Sorter(temparray, numrolls)
    
    INTEGER, INTENT(OUT):: temparray(numrolls)
    INTEGER, INTENT(IN):: numrolls
    
    DO i=1, (numrolls-1)
        min=temparray(i)
        pos=i
        DO k=i,numrolls
            IF (temparray(k)<min)THEN
                min=temparray(k)
                pos=k
            END IF
        END DO
        temp=temparray(i)
        temparray(i)=min
        temparray(pos)=temp
    END DO
    PRINT*, "Sorted Numbers"
    DO i=1, numrolls
    WRITE(*,23,ADVANCE="NO") temparray(i)
    23 FORMAT (I2)
    END DO
    PRINT*, " "
    END SUBROUTINE
    
    
    
    
    SUBROUTINE ComputeStats(temparray, sum, avg, variance, sdv)
    
    INTEGER, INTENT(IN):: temparray(numrolls)
    REAL, INTENT(OUT):: sum
    REAL, INTENT(OUT):: avg, variance, sdv
    
    DO i=1, numrolls
    sum=sum+temparray(i)
    END DO
    
    avg=sum/numrolls
    
    DO i=1, numrolls
    variance=variance+(((temparray(i)-avg)**2.0)/10)
    END DO
    sdv=variance**0.5
    
    END SUBROUTINE
    
    
    
    SUBROUTINE PrintStats( sum, avg, variance, sdv)
    
    
    REAL, INTENT(IN):: sum
    REAL, INTENT(IN):: avg, variance, sdv
    
    PRINT*, " "
    PRINT*, "Sum: ",sum
    PRINT '(1X,A,F5.3)', "Average: ",avg
    PRINT '(1X,A,F5.3)', "Variance: ",variance
    PRINT '(1X,A,F5.3)', "Standard Deviation: ",sdv
    
    END SUBROUTINE
    


    
END PROGRAM
EuropaDust
  • 333
  • 4
  • 12

3 Answers3

5

It looks like temparray is used before it is allocated.

To answer your question "what is a bus error?" : it generally means that your program tried to access a nonexistent address, or an address that doesn't have the proper alignment for that architecture (e.g. trying to read a 32-bit value from an address that's not aligned on a multiple of 4 bytes).

Jim Lewis
  • 43,505
  • 7
  • 82
  • 96
  • I do not understand: where is temparray used at all? To my understanding it is only allocated in the bottom line, and not used in the entire code shown? – tre95 Jun 02 '21 at 13:03
  • 1
    @tre95 : It looks like OP edited their post into a completely different question after the answers here were posted. I've rolled back the edits to restore the original context. – Jim Lewis Jun 02 '21 at 19:26
  • thanks for the effort, I was confused. // Shortly after reading this answer I found out that my SIGBUS error at a seemingly random code position that had always worked before was caused by running out of available memory on the node I used, maybe this helps someone else coming across this issue. – tre95 Jun 03 '21 at 11:54
4

Your allocation of temparray is too late. Try this:

ALLOCATE(numarray(numexps,numrolls), temparray(numrolls))

and delete the second ALLOCATE.

To debug it yourself next time, compile with -g option, like this:

$ gfortran -g code.f95

and run it under a debugger:

$ gdb a.out
gdb> run

it will then give you the location of the crash.

Amadan
  • 191,408
  • 23
  • 240
  • 301
4

The bus error you're getting here is issued by copying from numarray to temparray, before you allocate temparray. Just move the line ALLOCATE(temparray(numrolls)) before you enter the loop.

For a good comment about bus error, see Segmentation fault.

ifeitosa
  • 56
  • 1
  • 2
  • I moved it above the loop and it works now. Thanks so much! Another question I have is do you know how I can fix the part PRINT*, "Experiment ",i which is in the loop right below the allocate statement so that it prints Experiment 1 and Exp 2 and so on? It's another question that came up as I was debugging this. – EuropaDust Apr 13 '11 at 00:59
  • 1
    Adapt the format string from subroutine PrintStats to work with integer (something like '(1x,A,I)' -- this means, 1 space, one string field and a integer field -- or something adapted for your problem). Formats statements are very common in fortran, so get some familiarity with that with the compiler manual. – ifeitosa Apr 13 '11 at 04:11