Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29488 Discussions

Integer pointer and array bounds check in debug mode

ZlamalJakub
New Contributor III
873 Views
I am using in my program integer pointers:

real*8 data(10)
pointer (pData,Data)
nteger*4 NewCnt

pData=0
NewCnt=1
pData=LocalAlloc(LPTR,NewCnt*SizeOf(Data(1)))
...
some assignments

NewCnt=100 ! let say
...
pData=LocalRealloc(pData,NewCnt*SizeOf(Data(1)),IOR(LMEM_ZEROINIT,LMEM_MOVEABLE))

...

When I allocate space for more than 10 array elements (as was declared), I obtain error array bounds exceeded. I do not know what will be total number of elements at the compile time.

In DVF this does not happen (bounds of integer pointers were not checked).

Is there possibility to disable checking bounds of integer pointer arrays (other arays I want to check).


Is there some compiler switch? I did not found it.

Thank for advice

Jakub Zlamal

(I am using integer pointers instead of fortran pointers because it is windows application and allocatable arrays cannot be in data types.)


0 Kudos
5 Replies
JVanB
Valued Contributor II
873 Views

real*8 Data(*)

0 Kudos
ZlamalJakub
New Contributor III
873 Views
Quoting - Repeat Offender

real*8 Data(*)

Thank You, this solution works and Data array bounds are not checked, but I cannot look at first array elements when debugging code.

I used
real*8 Data(10)

to see first 10 elements.

Now I am using very big array declaration Data(1000) when I know that # of elements does not exceed 1000.

Jakub Zlamal


0 Kudos
IanH
Honored Contributor III
873 Views
Quoting - Quba
I am using integer pointers instead of fortran pointers because it is windows application and allocatable arrays cannot be in data types.


Could you elaborate a bit more on this restriction? At face value I don't think it is right, but maybe I'm missing something.

If you are using recent Intel Fortran releases you could perhaps use the C interoperability features of F2003 to make your life easier(*). As food for thought - in the following example LocalAlloc and friends are used (presumably for some unspecified good reason?) to provide the backing storage for a standard Fortran array pointer. With appropriate compiler flags you get full, working bounds checking too.

[cpp]!*******************************************************************************
!> Example of how to use Local* Win32 functions with "normal" fortran pointers.
!*******************************************************************************
PROGRAM LocalPtrDemo
  USE ISO_C_BINDING, ONLY: C_F_POINTER, C_LOC
  USE IFWIN
  IMPLICIT NONE
  REAL(8), POINTER :: my_array(:)
  INTEGER, PARAMETER :: real8_size = 8
  INTEGER my_size
  INTEGER rc
  !*****************************************************************************
  ! Use Win32 to allocate the underlying storage for our array.
  my_size = 1
  CALL C_F_POINTER(  &
      IntToCPtr(LocalAlloc(LPTR, my_size * real8_size)),  &
      my_array,  &
      [my_size] )
  my_array(1) = 10.0
  WRITE (*, 200) 'First element:', my_array(1)
  ! Change our minds about the size of that storage.
  my_size = 100
  CALL C_F_POINTER(  &
      IntToCPtr(LocalReAlloc( CPtrToInt(C_LOC(my_array)),  &
          my_size * real8_size, IOR(LMEM_ZEROINIT, LMEM_MOVEABLE) )),  &
      my_array,  &
      [my_size - 1] )   ! Deliberately shortened to demonstrate bounds check      
  WRITE (*, 200) 'First element (after re-alloc):', my_array(1)
  ! This would cause bounds check error because we've used my_size -1 above.
  !WRITE (*, 200) 'Last element (after re-alloc):', my_array(100)     
  WRITE (*, 200) 'Last element (after re-alloc):', my_array(99)
  ! Fortran "knows" how big the array is
  WRITE (*, 210) SIZE(my_array)
  ! Release the underlying storage.
  rc = LocalFree(CPtrToInt(C_LOC(my_array)))  
  IF (rc /= 0) THEN
    WRITE (*, 100) 'LocalFree failed'
  END IF
  100 FORMAT(A)
  200 FORMAT(A,F10.1)
  210 FORMAT('my_array is ',I0,' elements in size')
CONTAINS  
  !*****************************************************************************
  !> Converts an INTEGER(HANDLE) (that is actually a C-pointer), to a C_PTR
  !*****************************************************************************
  FUNCTION CPtrToInt(cp)
    USE ISO_C_BINDING, ONLY: C_PTR
    ! Arguments
    TYPE(C_PTR), INTENT(IN) :: cp
    ! Return type
    INTEGER(HANDLE) CPtrToInt
    !***************************************************************************
    CPtrToInt = TRANSFER(cp, CPtrToInt)
  END FUNCTION CPtrToInt  
  !*****************************************************************************
  !> Converts a C_PTR to an INTEGER(HANDLE)
  !*****************************************************************************
  FUNCTION IntToCPtr(int)
    USE ISO_C_BINDING, ONLY: C_PTR
    ! Arguments
    INTEGER int(HANDLE)
    ! Return type
    TYPE(C_PTR) IntToCPtr
    !***************************************************************************
    IntToCPtr = TRANSFER(int, IntToCPtr)
  END FUNCTION IntToCPtr  
END PROGRAM LocalPtrDemo[/cpp]


(*) Note emphasis on perhaps!

I use the transfer function to convert between the IFWIN style INTEGER(HANDLE) values returned by the Windows API and the F2003 TYPE(C_PTR) values. This might be a bit dodgy, is inherently not portable (but I guess so is use of IFWIN) and there might as a result be some 32/64 issues that I've not thought of. An alternative to transfer would be to write your own "one-liner" C functions that cast a void* pointer to integer or vice versa. I've also hardwired REAL(8)'s storage requirement to be 8 bytes - in a few years time I might be using the C_SIZEOF intrinsic instead.

Another possible simplification, if you are only using a few of the Win API's, would be to examine the INTERFACE for each relevant API function in IFWIN and children, and rewite the interface to take C_PTR's rather than INTEGER(LPVOID) or whatever.

IanH

0 Kudos
ZlamalJakub
New Contributor III
873 Views
Thank for Your answer, it looks very nice.

My problem is that my code is very old (10 years originally compiled by CVF) and I am using WIN API very much (it is MDI windows application not using QuickWin) so integer pointers are everywhere. But I think it will be usefull to implement Your code.

On line 61 should probably be:
INTEGER(HANDLE) int

Jakub
0 Kudos
IanH
Honored Contributor III
873 Views
Quoting - Quba
On line 61 should probably be:
INTEGER(HANDLE) int

Oops. Most definitely. An INTENT(IN) attribute wouldn't go astray either.
0 Kudos
Reply