4

I have this simple Fortran code and a function which I explicitly supply with an argument in the main program. The code is below:

   implicit none

   real*8 rrr,x
   external tttt

   x = rrr(10)

   end

   function rrr(seed)
   integer seed, k
   real*8 rrr
   k = 7
   seed = 16807 * ( seed - k * 127773 ) - (k * 2836)
   print*,seed
   rrr = seed / 2.
   end

It compiles, however upon run it produces the following error:

Program received signal SIGBUS: Access to an undefined portion of a memory object.

Backtrace for this error:
#0  0x10f43bfe6
#1  0x10f43b7ac
#2  0x7fff89740529
#3  0x10f433d78
#4  0x10f433e2c
#5  0x10f433e6e
Bus error: 10

Any ideas what maybe causing the error? I use gfortran to compile my code.

user3578925
  • 881
  • 3
  • 16
  • 26

1 Answers1

2

You are modifying the seed in the function. You cannot do that, because it is constant 10. You cannot modify seed in the function if you pass something, which is not definable into it. A constant literal is not definable. Variables normally are.

Also, don't use external functions. Use modules, or put your functions into the contains section which makes them internal. That way the caller will have explicit interface and can check correctness of the code.

In particular the error you made can be avoided automatically if you make the function argument intent(in) and check the interfaces. Even without modules many compilers can find out the problem if you enable all warnings and error checks. For example -g -fcheck=all -Wall -fbacktrace in gfortran.

Fix for you:

   real*8 :: x
   integer :: iseed

   iseed = 10
   x = rrr(iseed)

   contains

     function rrr(seed)
       real*8 :: rrr
       integer, intent(in) :: seed
       integer :: kk

       k = 7
       seed = 16807 * ( seed - k * 127773 ) - (k * 2836)

       print *,seed
       rrr = seed / 2.
     end function

   end program
  • @Vladimir F, I am sorry for being such a layman but how do I solve the problem then? – user3578925 Aug 15 '16 at 19:56
  • @user3578925 You can pass the thing you want as a variable, or use the `value` attribute for the dummy argument, or create a local copy. I'm pretty sure we've seen a very similar/useful question recently, but I can't immediately find it. – francescalus Aug 15 '16 at 19:57
  • But for `value` you need that explicit interface. – Vladimir F Героям слава Aug 15 '16 at 19:58
  • OK, if I use y = 10 and then do "x = rrr(y)" that works. Honestly, I don't understand that. I have no problem calling subroutines with explicit numbers i.e, I can do "call whatever (10, output)" and that will work, as long as the number 10 is defined as an integer in the subroutine. – user3578925 Aug 15 '16 at 20:02
  • 2
    The problem is that you modify it inside the function! You cannot modify constant literal `10`. You must simply accept that, it is a Fortran rule. – Vladimir F Героям слава Aug 15 '16 at 20:02
  • @Vladimir F, ahhhh I am so stupid! Of course! :) Thanks guys! – user3578925 Aug 15 '16 at 20:03
  • @user3578925 using interfaces can help avoid these sorts of problems (through preventing compilation). You might want to get out the Fortran documentation, in particular the [interfaces topic](http://stackoverflow.com/documentation/fortran/2882/explicit-and-implicit-interfaces#t=201608160718159656782). – d_1999 Aug 16 '16 at 07:19