Skip to content

How to debug c/fortran on cheme server?

Page last updated on: 2019-10-14

Sample code

Sample code (Monte Carlo sampling) mc.f is used in this example.

Show source code mc.f
        program baby_mc
c
c   Monte Carlo for a trivial problem - 10 states with energy E(i)=i
c   so p(i)=wxp(- beta * E(i)) / Z   where  Z=sum exp(- beta * E(i))
c
        dimension n(10)
c
c       warm up random number generator
c
        idum=193728181
        do i=1,1000
                x=ran1(idum)
        enddo
c
c       input parameters
c
    print*, 'enter beta and number of cycles'
        read*, beta,ncycles
c
c       initial state
c
        i=1+10*ran1(idum)
c
        e=0
        n=0
        do icycle=1,ncycles
                j=1+10*ran1(idum)       ! new state
                if(j.lt.i) then
                        i=j             ! accept if lower energy
                else
                        z=ran1(idum)    ! accept or not by metropolis test
                        if(z.lt.exp(-beta*(j-i))) i=j
                endif
                e=e+i
c
                n(i)=n(i)+1
        enddo
c
c       output
c
        print*, e/float(ncycles)
        print '(10f8.5)', n/float(ncycles)
c
        stop
        end
c
1
      FUNCTION ran1(idum)
      INTEGER idum,IA,IM,IQ,IR,NTAB,NDIV
      REAL ran1,AM,EPS,RNMX
      PARAMETER (IA=16807,IM=2147483647,AM=1./IM,IQ=127773,IR=2836,
     *NTAB=32,NDIV=1+(IM-1)/NTAB,EPS=1.2e-7,RNMX=1.-EPS)
      INTEGER j,k,iv(NTAB),iy
      SAVE iv,iy
      DATA iv /NTAB*0/, iy /0/
      if (idum.le.0.or.iy.eq.0) then
        idum=max(-idum,1)
        do 11 j=NTAB+8,1,-1
          k=idum/IQ
          idum=IA*(idum-k*IQ)-IR*k
          if (idum.lt.0) idum=idum+IM
          if (j.le.NTAB) iv(j)=idum
11      continue
        iy=iv(1)
      endif
      k=idum/IQ
      idum=IA*(idum-k*IQ)-IR*k
      if (idum.lt.0) idum=idum+IM
      j=1+iy/NDIV
      iy=iv(j)
      iv(j)=idum
      ran1=min(AM*iy,RNMX)
      return
      END

First of all, you need to compile with "-g" option to make a debuggable code. Some common compiler flags are:

Flag Example Explanation
-g gfortran -g mc.f Turn on debug information
-Wall gfortran -Wall mc.f Turn on all warning
-O3 gfortran -O3 mc.f optimize code, but may disrupt debug info
-o fname gfortran -o mc mc.f specify output file
-c gfortran -c mc.f compile to object file only
-l ... load library by name
-L ... load library path
-I ... load include path
-static gfortran -static mc.f make static execytable
-fdefault-integer-8 use 8 byte long integer
-fdefault-real-8 use 8 byte double float

Some flags can be mixed and used together.

Compile using Makefile

If you are working on a programming project, the chance is you may need to to compile program again and again. Make tool comes handy in this situation.

Simply speaking, make tool reads a file and interpret three key elements: target, dependency and action.

For example, to make an executable mc from mc.f by running command gfortran -o mc mc.f, we prepare a file named "Makefile":

mc: mc.f
    gfortran -o mc mc.f

The white space in action line has to be a Tab.

Then, run

make

See what happens. What if you run make again?

mc is the target, and mc.f is dependency. The first line means file mc depends on file mc.f. If mc.f is newer than mc, then the action line, which is also called recipe, will be triggered.

The target can be unconditional, and it is usefule to use this fueture to clean the directory.

mc: mc.f
    gfortran -o mc mc.f

clean:
    rm mc

When you run "make clean", it will trigger the rm mc command.

With the above features, we can set up two ways of compiling a program, one for error checking and debugging, and one for optimization.

mc: mc.f
    gfortran -o mc mc.f

clean:
    rm mc

g:
    gfortran -Wall -g -o mc mc.f

o:
    gfortran -O3 -o mc mc.f
Then use make g to compile code for debug and make o for optimize.

Command line debugger: gdb

Useful case: quick analysis of a core file.

Check if core dump is enabled:

ulimit -c

If it reports 0, set it to unlimited:

ulimit -c unlimited

Edit code to exceed array boundary, and run code to create a core dump. Line 35: n(i+100000)=n(i)+1

Create debuggable code: make g

Run code: ./mc It should crash and leave a core file.

Debug:

gdb mc core
bt

This will reveal where and why the error occurred.

Nemiver, GUI of gdb

Nemiver is a GUI front end of gdb.

Common operations:

  • Load core file
  • Load executable
  • Set break point: click the space on right of line number or F8
  • Run/continue to breakpoint: F5
  • Run to current line: F11
  • Step over: F6
  • Step in: F7
  • Stop a running session: F9
  • Show variables

Last update: 2019-10-14