Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Nata_pri
Novice
751 Views

GetOpenFileName gives error in virtual memory

Jump to solution

Dear Colleagues! Please help me overcome the problem. As soon as I turn to the GetOpenFileName program, an error "forrtl: severe (41): usufficiant virtual memory" immediately occurs when opening the test file "test.dat". does not work on all versions of compilers (11,18,19). I would be grateful for your help!

program fileopenroot
use nozspe
call initarrs
end 
subroutine fileopen(file_spec,ilen)

use comdlg32
use user32 
implicit none
character(512) :: file_spec
integer ilen
type(T_OPENFILENAME) ofn
integer*4 NFOBR,status
integer*4 in1
character(*),parameter :: filter_spec = &
  "Text Files"C//"*.dat"C// &
  "Fortran Files"C//"*.dat;"C
character*512   OIFIL
ofn%lStructSize = SIZEOF(ofn)
ofn%hwndOwner = GetForegroundWindow()
ofn%hInstance = NULL  ! For Win32 applications, you
                      ! can set this to the appropriate
                      ! hInstance
                      !
ofn%lpstrFilter = loc(filter_spec)
ofn%lpstrCustomFilter = NULL
ofn%nMaxCustFilter = 0
ofn%nFilterIndex = 1 ! Specifies initial filter value
ofn%lpstrFile = loc(file_spec)
ofn%nMaxFile = sizeof(file_spec)
ofn%nMaxFileTitle = 0
ofn%lpstrInitialDir = NULL  ! Use Windows default directory
ofn%lpstrTitle = loc(""C)
ofn%Flags = OFN_PATHMUSTEXIST
ofn%lpstrDefExt = loc("txt"C)
ofn%lpfnHook = NULL
ofn%lpTemplateName = NULL

status = GetOpenFileName(ofn)

if (status .eq. 0) then
  type *,'No file name specified'
else
  ilen = INDEX(file_spec,CHAR(0))
  type *,'Filespec is ',file_spec(1:ilen-1)
  if (IAND(ofn%flags,OFN_READONLY) /= 0) &
    type *,'Readonly was requested'
  end if
  NFOBR=58
         OIFIL="d:/test.dat"C
        in1=108000000
        OPEN(NFOBR,FILE=trim(OIFIL),STATUS='unknown',ACCESS='DIRECT',RECL=in1,FORM='UNFORMATTED',SHARED)
        WRITE(NFOBR,REC=1) IN1
        CLOSE(NFOBR)
        OPEN(NFOBR,FILE=trim(OIFIL),STATUS='unknown',ACCESS='DIRECT',RECL=in1,FORM='UNFORMATTED',SHARED)
        READ(NFOBR,REC=1) IN1
        CLOSE(NFOBR)
return
end 
          subroutine InitArrs
           use nozspe
           character*512 :: file_spec = ""C
           integer*4 ilen
           allocate (ASHM(Ndim1D),ASHN(Ndim1D),SHM(Ndim1D),SHN(Ndim1D),AASHM(Ndim1D+1),AASHN(Ndim1D+1))
           allocate (D(ndimB),P(ndimB),T(ndimB),E(ndimB),WM(ndimB),WN(ndimB),TMPARR((ndimB+Ndim1D)*2),TMPARR2((ndimB+Ndim1D)*2))
           allocate (DFUEL(ndimB))
           allocate (EP1(ndimB))
           allocate (ASHL(Ndim1D),VLine(Ndim1D*20),DENS(ndimB))
           allocate (ninfpl(ndimB),ninf(ndimB))
           allocate (NWaveV(Ndim1D),ovol(ndimB),OWaveV(Ndim1D))
           call fileopen(file_spec,ilen)
           return
          end
      
      module nozspe
      IMPLICIT REAL*8 (A-H,P-Z), LOGICAL*1 (O)
      INTEGER,parameter :: ndim=3000,LdimB=3000,ndimB=10000000
      INTEGER,parameter :: Ndim1D=10001
	  real(8), allocatable, dimension(:):: ASHM,ASHN,SHM,SHN,AASHM,AASHN,D
      real(8), allocatable, dimension(:):: P,T,E,WM,WN,TMPARR
      real(8), allocatable, dimension(:):: DFUEL,TMPARR2,EP1,ASHL
      real(8), allocatable, dimension(:):: VLine,DENS
      integer, allocatable, dimension(:):: NWaveV,ninfpl,ninf
      logical(1), allocatable, dimension(:):: ovol,OWaveV
      end module nozspe

  

Nata_pri_0-1594850470718.png

 

0 Kudos
1 Solution
Steve_Lionel
Black Belt Retired Employee
683 Views

I think that for your particular system, that 400KB allocation is right on the edge of what your system can handle, and calling GetOpenFileName caused Windows to allocate some more, pushing you over the edge. On my PC, it made no difference - it failed either way.

Do you really need a RECL that long? What exactly are you trying to do here?  I agree that Xeffort is not yet 64-bit ready (and may never be.)

View solution in original post

25 Replies
Nata_pri
Novice
635 Views

If you comment out the GetOpenFileName statement, the program works without errors.

 

andrew_4619
Honored Contributor I
625 Views

Well I glanced down your code and the first thing that jumped out at me was I have had issues with making null terminated C strings with the non-standard "text"C syntax. I always use "text"//achar(0). But the second thing that I note is that filter_spec needs double null termination at the end //achar(0)//achar(0) the first null ending the last string and the second ending  the string list.

It may be that without that the SDK routine goes looking further along in memory for that non-existent termination and then bad things happen.

 

Nata_pri
Novice
605 Views

Dear andrew_4619!
This is a standard example that comes with the compiler. Unfortunately, replacing with // achar (0) did not fix the problem. Thank you!

Nata_pri
Novice
603 Views

GetOpenFileName is a dummy call, you can select any file on the disk.

andrew_4619
Honored Contributor I
601 Views

If you insist on using the C notation you will still need:

character(*),parameter :: filter_spec = & "Text Files"C//"*.dat"C// & "Fortran Files"C//"*.dat;"C//""C

note I changed the end of the string.

 

 

Nata_pri
Novice
598 Views

Dear andrew_4619!

I do not insist in any way, I just state the fact that neither one nor the other method proposed by you solved the problem. Thank you!

Nata_pri
Novice
596 Views
program fileopenroot
use nozspe
call initarrs
end 
subroutine fileopen(file_spec,ilen)

use comdlg32
use user32 
implicit none
character(512) :: file_spec
integer ilen
type(T_OPENFILENAME) ofn
integer*4 NFOBR,status
integer*4 in1
character(*),parameter :: filter_spec = &
  "Text Files"//char(0)//"*.dat"//char(0)// &
  "Fortran Files"//char(0)//"*.dat;"//char(0)//char(0)
character*512   OIFIL
ofn%lStructSize = SIZEOF(ofn)
ofn%hwndOwner = GetForegroundWindow()
ofn%hInstance = NULL  ! For Win32 applications, you
                      ! can set this to the appropriate
                      ! hInstance
                      !
ofn%lpstrFilter = loc(filter_spec)
ofn%lpstrCustomFilter = NULL
ofn%nMaxCustFilter = 0
ofn%nFilterIndex = 1 ! Specifies initial filter value
ofn%lpstrFile = loc(file_spec)
ofn%nMaxFile = sizeof(file_spec)
ofn%nMaxFileTitle = 0
ofn%lpstrInitialDir = NULL  ! Use Windows default directory
ofn%lpstrTitle = loc(""//char(0))
ofn%Flags = OFN_PATHMUSTEXIST
ofn%lpstrDefExt = loc("txt"//char(0))
ofn%lpfnHook = NULL
ofn%lpTemplateName = NULL

status = GetOpenFileName(ofn)

if (status .eq. 0) then
  type *,'No file name specified'
else
  ilen = INDEX(file_spec,CHAR(0))
  type *,'Filespec is ',file_spec(1:ilen-1)
  if (IAND(ofn%flags,OFN_READONLY) /= 0) &
    type *,'Readonly was requested'
  end if
  NFOBR=58
         OIFIL="d:/test.dat"//char(0)
        in1=108000000
        OPEN(NFOBR,FILE=trim(OIFIL),STATUS='unknown',ACCESS='DIRECT',RECL=in1,FORM='UNFORMATTED',SHARED)
        WRITE(NFOBR,REC=1) IN1
        CLOSE(NFOBR)
        OPEN(NFOBR,FILE=trim(OIFIL),STATUS='unknown',ACCESS='DIRECT',RECL=in1,FORM='UNFORMATTED',SHARED)
        READ(NFOBR,REC=1) IN1
        CLOSE(NFOBR)
return
end 
subroutine InitArrs
           use nozspe
           character*512 :: file_spec = ""//char(0)
           integer*4 ilen
           allocate (ASHM(Ndim1D),ASHN(Ndim1D),SHM(Ndim1D),SHN(Ndim1D),AASHM(Ndim1D+1),AASHN(Ndim1D+1))
           allocate (D(ndimB),P(ndimB),T(ndimB),E(ndimB),WM(ndimB),WN(ndimB),TMPARR((ndimB+Ndim1D)*2),TMPARR2((ndimB+Ndim1D)*2))
           allocate (DFUEL(ndimB))
           allocate (EP1(ndimB))
           allocate (ASHL(Ndim1D),VLine(Ndim1D*20),DENS(ndimB))
           allocate (ninfpl(ndimB),ninf(ndimB))
           allocate (NWaveV(Ndim1D),ovol(ndimB),OWaveV(Ndim1D))
           call fileopen(file_spec,ilen)
           return
          end
Nata_pri
Novice
594 Views

the same error

Nata_pri
Novice
591 Views
andrew_4619
Honored Contributor I
583 Views

I am guessing that perhaps if you had done the file dialog before the allocated it would have worked but maybe the last allocate might have failed ? I usually have STAT= on all allocates to check they worked and stop a potential crash.

 

Nata_pri
Novice
576 Views

Without operator GetOpenFileName there were no problem with allocate of memory (16 Gb). Yes, now I also will use "Stat" )).

Steve_Lionel
Black Belt Retired Employee
561 Views

No, the code you are using is NOT the example that comes with the compiler. I should know, as I wrote the example (or at least revised it at one time.)

This is the example and it works:

program fileopen
use comdlg32
implicit none

! Declare structure used to pass and receive attributes
!
type(T_OPENFILENAME) ofn

! Declare filter specification.  This is a concatenation of
! pairs of null-terminated strings.  The first string in each pair
! is the file type name, the second is a semicolon-separated list
! of file types for the given name.  The list ends with a trailing
! null-terminated empty string.
!
character(*),parameter :: filter_spec = &
  "Text Files"C//"*.txt"C// &
  "Fortran Files"C//"*.f90;*.f"C//""C

! Declare string variable to return the file specification.
! Initialize with an initial filespec, if any - null string
! otherwise
!
character(512) :: file_spec = ""C
integer status,ilen
ofn%lStructSize = SIZEOF(ofn)
ofn%hwndOwner = NULL
ofn%hInstance = NULL  ! For Win32 applications, you
                      ! can set this to the appropriate
                      ! hInstance
                      !
ofn%lpstrFilter = loc(filter_spec)
ofn%lpstrCustomFilter = NULL
ofn%nMaxCustFilter = 0
ofn%nFilterIndex = 1 ! Specifies initial filter value
ofn%lpstrFile = loc(file_spec)
ofn%nMaxFile = sizeof(file_spec)
ofn%nMaxFileTitle = 0
ofn%lpstrInitialDir = NULL  ! Use Windows default directory
ofn%lpstrTitle = loc(""C)
ofn%Flags = OFN_PATHMUSTEXIST
ofn%lpstrDefExt = loc("txt"C)
ofn%lpfnHook = NULL
ofn%lpTemplateName = NULL

! Call GetOpenFileName and check status
! 
status = GetOpenFileName(ofn)
if (status .eq. 0) then
  type *,'No file name specified'
else
  ! Get length of file_spec by looking for trailing NUL
  ilen = INDEX(file_spec,CHAR(0))
  type *,'Filespec is ',file_spec(1:ilen-1)
  ! Example of how to see if user said "Read Only"
  !  
  if (IAND(ofn%flags,OFN_READONLY) /= 0) &
    type *,'Readonly was requested'
end if
end program fileopen
Nata_pri
Novice
547 Views

Dear Steve! Of course the original code has been changed. The reference concern using // char (0) instead of "" C . For me, the question remained unclear, how such an insignificant programm GetOpenFileName could cause problems with long memory addressing. Does this mean there is a problem with the GetOpenFileName program? Can you answer as a Fortran Guru?

andrew_4619
Honored Contributor I
538 Views

GetOpenFileName is a standard part of the windows  system used in many thousands of applications, it is not Fortran specific. It is unlikely there is a problem with it as lots of people would have a problem. You have experience a memory addressing problem that can have many potential causes. The missing double null termination in your code was a bug, it may not be related to the problem you experienced but is still a bug as the routine would search beyond your string  until it found a null address or hit a predefined buffer limit value. The results of that would be hard to predict.

GVautier
New Contributor II
536 Views

"Insignificant" nothing is insignificant with memory.

The insignificant statement :

strcpy(from,to);

will certainly cause an access violation in memory if there is no char(0) at the end of string from.

 

 

Steve_Lionel
Black Belt Retired Employee
526 Views

There is no difference between ""C and CHAR(0), other than that ""C is non-standard. 

The program you posted above is incomplete, as it uses a module you did not supply.

Nata_pri
Novice
520 Views

Module is at the end of first post

Steve_Lionel
Black Belt Retired Employee
515 Views

Ok. The immediate cause of the Insufficient virtual memory error is:

        in1=108000000
        OPEN(NFOBR,FILE=trim(OIFIL),STATUS='unknown',ACCESS='DIRECT',RECL=in1,FORM='UNFORMATTED',SHARED)

 

You are opening the file with a RECL of 108000000*4 bytes, or 432,000,000 bytes. As part of the OPEN, the run-time library allocates a buffer large enough to hold a whole record. At least in a 32-bit configuration, that large a single allocation fails. If I build the program as x64, the OPEN succeeds.

The use of GetOpenFileName is a "red herring" - it has no effect on the OPEN problem. I removed the call and still saw the error.

One other error I spotted is this:

 OIFIL="d:/test.dat"//char(0)

Do not append a NUL to file specifications you'll use in OPEN. This is probably harmless, but is still an error. 

 

Nata_pri
Novice
319 Views

Thanks a lot, Steve! Unfortunately, I have to write an application under win32 because of I use the Xeffort library. I am not such an experienced user of visual fortran. I tried unsuccessfully to convert this library to win64 (((. This library helped me to draw directly inside of the QWin dialogue, for example.

Nata_pri
Novice
317 Views

But nevertheless compare 2 results

Nata_pri_0-1595012261952.png

Nata_pri_1-1595012424781.png

Maybe I am stupid, but I  can't finally understand this result. (I understand your explanation concern Open, etc). 

 

Reply