Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
New Contributor I
23 Views

conversion from int * to int may lose significant bits

Jump to solution

  I am porting a FORTRAN program from DEC alpha to LINUX.  The FORTRAN program has one piece that is written in C.   

I am getting an warning that may be causing a memory issue in the arrays for some input problems.  Heating 72 is a very large code.:

h7lib.c(23): warning #810: conversion from "int *" to "int" may lose significant bits

*addr = (int)addrp;

Here is the routine in h7lib.c being called by htng72.f

18  void getmem_(int *number,int *size,int *array,int *addr,int *offset)
19  { int *malloc();
20    int *addrp;
21    addrp = malloc((*number)*(*size));
22   *offset = (int)(addrp-array)*sizeof(int)/(*size);
23   *addr = (int)addrp;
24  }

Here is the call from htng72.f

integer*8 addr

c *** Determine pointers for phase3 variably dimensioned arrays,
c *** determine number of words of memory required, and allocate
c *** memory arrays.
      call ptr3
      lmck = limit
      call chgmem(lmck,lword,d,addr,offset)
      if(addr.ne.0)then
        call phase3(d(offset+1),d(offset+1),d(offset+1),lmck)
      else
        write(io,3000)
        stop
      endif

 

I am not sure how to rewrite the *addr.int.  so that I don't  get the warning.

0 Kudos

Accepted Solutions
Highlighted
Employee
23 Views

Hello,

This warning seems to be specific to C code.  If you are developing on 64 bit, then the size of "int" is likely 32 bit, but the size of "int*" would be 64 bit.  Thus, assigning pointer to integer would lose data.

Eugene Epshteyn

View solution in original post

0 Kudos
5 Replies
Highlighted
Employee
24 Views

Hello,

This warning seems to be specific to C code.  If you are developing on 64 bit, then the size of "int" is likely 32 bit, but the size of "int*" would be 64 bit.  Thus, assigning pointer to integer would lose data.

Eugene Epshteyn

View solution in original post

0 Kudos
Highlighted
New Contributor I
23 Views

Thank you.

Jump to solution

Thank you.

I rewrote the line *addr=(int)addrp;

to "addr=(long)addrp.   got a clean compile.

Thanks for your help.

0 Kudos
Highlighted
Employee
23 Views

> addr=(long)addrp

Jump to solution

addr=(long)addrp

Well, you hushed the compiler warning, but it's not clear, whether this will generate the right code.  If you compile for 32 bit, this will probably work.  If you compile for 64 bit, this will most likely generate wrong code.  Something to keep in mind, if you start seeing strange runtime behavior.

Eugene Epshteyn
0 Kudos
Highlighted
New Contributor I
23 Views

Eugene,

I'm still fighting the problem.   Mainly, the inputs are building larger plots are yielding '0' sized plot files.  Inputs with smaller plots are not affected.   Based on my debug, the segmentation fault occurs after leaving the h7lib (initializing offsets) and calling phase3.f which writes out the plots using the dimensions initialized from the h7lib.c.  The error mentions the 'd' array doesn't have enough memory.

Everything working fine on the Tru64 alpha(when the server is up long enough, and not so well porting to intel 64 f90.  I am compiling for 64 bit.   I'm not using any options on the build, just mimicking the build under Tru 64.  Not sure how a 32 bit integer was introduced since we don't have any 32 bit environments or platforms.  

Not sure what direction to go at this point.

Debug information:

102             call phase2(d(offset+1),d(offset+1),d(offset+1),lmck)
(gdb) step
phase2 (c=<error reading variable: Cannot access memory at address 0xfffffffff7f1a010>, ic=<error reading variable: Cannot access memory at address 0xfffffffff7f1a010>,
    lc=<error reading variable: Cannot access memory at address 0xfffffffff7f1a010>, limit0=212236) at phase2.f:52
 

0 Kudos
Valued Contributor III
23 Views

Quote:Jon D. wrote:

Jump to solution

Jon D. wrote:

.. I'm still fighting the problem.   .. Not sure what direction to go at this point. ..

@Jon D.,

Firstly, note it's been officially Fortran and not FORTRAN since 1991 i.e., following the ISO/IEC 1539 standard.

Secondly, the code snippets you have shown are all non-standard and as such, they are highly likely not to be portable and this is at the crux of the problem you're fighting.

If you plan to work further with your code, note with the enhancements in standard Fortran language with dynamic allocation and a host of other facilities with arrays, you may be able to get rid if your getmem_ C procedure entirely.  So 'modernizing' your Fortran code and to make use of standard, intrinsic and (IMO) much safer and cleaner memory management facilities with the ALLOCATABLE attribute in Fortran compared to what one can do with C and even C++ is what I would recommend.  Toward this, you may want to review the references in https://software.intel.com/en-us/blogs/2013/12/30/doctor-fortran-in-its-a-modern-fortran-world

But if you're looking for a quick fix, think MWE: https://en.wikipedia.org/wiki/Minimal_Working_Example. ; Create one involving getmem_ C procedure and your phase2 (or phase3) Fortran subroutine in a small Fortran main program and see if you can first reproduce the problem and then to diagnose and resolve the issue.  My immediate suggestion will be:

1) try using size_t type in your getmem_ C procedure:

#include <stdlib.h>

void getmem_(int *number, int *size, int *array, size_t *addr, size_t *offset)
{
   size_t nelem;
   size_t selem;
   nelem = (size_t)(*number);
   selem = (size_t)(*size);
   *addr = (size_t)malloc( nelem*selem );
   *offset = (*addr - (size_t)array)*sizeof(size_t)/selem;
}

2) use C_size_t named constant from ISO_C_BINDING in your Fortran code: https://software.intel.com/en-us/fortran-compiler-18.0-developer-guide-and-reference-named-constants

      use iso_c_binding, only : c_size_t
      ..
      integer(kind=c_size_t) :: addr
      integer(kind=c_size_t) :: offset
c *** Determine pointers for phase3 variably dimensioned arrays,
c *** determine number of words of memory required, and allocate
c *** memory arrays.
      ..
      call chgmem(lmck,lword,d,addr,offset)
      if (addr /= 0) then
        call phase3(d(offset+1),d(offset+1),d(offset+1),lmck)
      else
        write(io,3000)
        stop
      end if

 

0 Kudos