0

I want to open a MAT-file in fortran and I followed the example file. The compilation and linking happen without any errors or warnings.

This is the makefile:

FC = gfortran
FCFLAGS = -g -fcheck=all -Wall
INCLUDES = -I/usr/local/matlab2008a/extern/include
LFLAGS = -L/usr/local/matlab2008a/bin/glnxa64
LIBS = -lmat -lmx
LDFLAGS = "-Wl,-rpath,/usr/local/matlab2008a/bin/glnxa64"

main: main.o param.o dmotifs.o ssa.o
    $(FC) $(LFLAGS) $(LIBS) $(LDFLAGS) -o main main.o param.o dmotifs.o ssa.o  
param.o: param.f90
    $(FC) $(FCFLAGS) -c $<    
dmotifs.o: dmotifs.f90 param.o
    $(FC) $(FCFLAGS) -c $<    
ssa.o: ssa.f90 dmotifs.o
    $(FC) $(FCFLAGS) -c $<   
main.o: main.f90 param.o dmotifs.o ssa.o
    $(FC) -c -cpp $(FCFLAGS) $(INCLUDES) $<    
clean:
    rm -f *.o *.mod *.MOD

However when I am running the script I am getting segmentation fault error.

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0  0x37B4C19497
#1  0x37B4C19ADE
#2  0x37B1E358EF
#3  0x7F1EA50EA7C1
#4  0x401A69 in MAIN__ at main.f90:75
Segmentation fault

This is the main code:

#include "fintrf.h"

PROGRAM main     
USE ssa
IMPLICIT NONE

CHARACTER(LEN=6) :: argfun
TYPE(fhandle), DIMENSION(13) :: fmotifs
TYPE(funnames), DIMENSION(13) :: fnames
TYPE(PRM) p
REAL, DIMENSION(4) :: y0
REAL tf
REAL, ALLOCATABLE, DIMENSION(:) :: t
REAL, ALLOCATABLE, DIMENSION(:,:) :: y
TYPE(OPTIONS) opt
INTEGER fin
REAL nM2m

! MAT-FILE Declarations !

INTEGER*8 matOpen, matGetDir !, matGetNextVariable
INTEGER matGetVariableInfo
INTEGER mp, dir, adir(100), pa
INTEGER mxGetM, mxGetN, matClose
INTEGER ndir, i, clstat
CHARACTER*32 names(100) !, name

!===========================!


nM2m=1.355178815844751e3;

opt%numsample=2000
tf=1000000

call get_command_argument(1,argfun)

call makemotifs(fnames,fmotifs)
call getparamdef(p)

if(all(fnames(:)%fn .NE. argfun)) then
    write(*,*) "No such motif: ",argfun
    write(*,*) "Input format-> main <motifname>"
    stop
else


    fin=fchton(argfun)  
    y0=nint(nM2m*analys(p,argfun))


    !*** ==> OPEN MAT-file <== ***!

    mp=matOpen('./PRMS_lxr_29Apr15.mat','r')

    if (mp .eq. 0) then
         write(6,*) "Can't open MAT-file"
         stop
    end if

    dir = matgetdir(mp, ndir)

    if (dir .eq. 0) then
         write(6,*) "Can't read MAT-file-directory."
         stop
    endif

    call mxCopyPtrToPtrArray(dir, adir, ndir)

    do 20 i=1,ndir
         call mxCopyPtrToCharacter(adir(i), names(i), 32)
 20 continue

    write(6,*) 'Directory of Mat-file:'

    do 30 i=1,ndir
        write(6,*) names(i)
 30 continue

    write(6,*) 'Getting Header info from first array.'
    pa = matGetVariableInfo(mp, names(1))
    write(6,*) 'Retrieved ', names(1)
    write(6,*) '  With size ', mxGetM(pa), '-by-', mxGetN(pa)
    call mxDestroyArray(pa)

    clstat=matClose(mp)

    call gillespie(fmotifs(fin),y0,p,tf,opt,t,y)

end if

Line 75 (as pointed out in the error message is): dir = matgetdir(mp, ndir)

I have no clue how to fix the issue. If I comment out the MAT-file opening part then everything works fine. The MAT-file contains a float 3D array (9x5x10000) and two scalars.

EDIT

As it seems that for 64bit systems, the pointers have to be declared as integer*8 instead of integer. When I did this I am again getting a segmentation fault at this line:
      call mxCopyPtrToPtrArray(dir, adir, ndir)

Mathworks documentation on this topic is almost nothing and they make it seem to be quite an easy routine job. Is there anyone on earth who has actually opened a MAT-file on fortran? Can someone please share their scripts?

WYSIWYG
  • 494
  • 6
  • 23
  • @AlexanderVogt he has some backtrace there, line 75. – Vladimir F Героям слава May 13 '15 at 10:35
  • Double check you call the mat* routines correctly, e.g., the number of arguments and their types. If they had some module with explicit interfaces, that would be the best. – Vladimir F Героям слава May 13 '15 at 10:36
  • Actually I am giving up usage of MAT-files. Using HDF5 is an infinitely better option. Retaining this post for general interest. – WYSIWYG May 14 '15 at 07:00
  • A MAT file today is a restricted form of HDF5 file. It is difficult to diagnose the problem in your later edit without seeing the actual code. – IanH May 14 '15 at 21:11
  • @IanH this is the actual code. The modules used in the program just have subroutines for doing some calculations. And this error happens even if I remove the statements that require those modules. – WYSIWYG May 15 '15 at 05:15
  • @IanH wrt MAT and HDF5. Yeah they are related but the former has poor documentation for usage in external applications. The issue with Mathworks is that they tend to give partial support for external applications. [unrelated issue] Even the EPS generated by matlab has some messed up co-ordinates and don't get positioned properly in LaTeX. I generally resave them using some external application. HDF5 has decent examples and it just took a little time to understand them and get things done. – WYSIWYG May 15 '15 at 05:29
  • Your edit with the new error refers to use of the `integer*8` extension to standard Fortran. The code in the question has not been updated to reflect this. – IanH May 17 '15 at 04:54

1 Answers1

2

From the length of the addresses in the error message it looks like you are on a 64 bit system.

You have declared, and are storing, the results of most of the mat* functions in a default integer. This is probably only a 32 bit type. The mat* functions actually return a machine pointer, which will be 64 bits on a 64 bit machine.

The example code you linked to likely assumes a 32 bit platform.

Adjust your declarations for the mat* functions and the variables that get assigned the results of invoking those functions appropriately. Perhaps INTEGER(C_INTPTR_T), where C_INTPTR_T is from ISO_C_BINDING.

The mathworks provides an archaic C preprocessor means of specifying the relevant type (for example, the return type of matOpen is mwPointer), which the preprocessing changes into the appropriate integer kind. Personally I prefer to use my own interfaces, written using the C interoperability features of Fortran 2003.

IanH
  • 21,026
  • 2
  • 37
  • 59
  • 2
    It may also be useful to point to the comment "Replace integer by integer*8 on the DEC Alpha 64-bit platform" in the [example](http://www-rohan.sdsu.edu/doc/matlab/techdoc/matlab_external/ch05ma11.html), because it seems to suggest which variables/functions to be changed in the declaration part. – roygvib May 13 '15 at 12:21
  • Thanks. After I replaced `integer` with `integer*8` for the pointer declarations, I am still getting segmentation fault at line 82: `call mxCopyPtrToPtrArray(dir, adir, ndir)` – WYSIWYG May 14 '15 at 05:58