# On Linux moving 32 bit program to 64 bit: 3 segmentation faults for invalid memory references (malloc?)

**URL:** <https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128>\
**Category:** Help\
**Created:** [April 4, 2022, 4:17pm UTC](https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128 "2022-04-04T16:17:50Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![giraffe](https://avatars.discourse-cdn.com/v4/letter/g/f1d935/32.png) [@giraffe](https://fortran-lang.discourse.group/u/giraffe)\
**Post date:** [April 4, 2022, 4:17pm UTC](https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128/1 "2022-04-04T16:17:50Z")

</div>

The program runs perfectly on 32 bit Linux. It compiles on 64 bit but gives the following errors.

I have four files. One of these (named STUFF) is included into the Fortran file named A.f. A.f calls routines in file B.c.

The third file (named B.c) is a C file that has three functions. If I don’t comment out most of the first two functions in this file and where I just leave the first “then clause” in each of the if-then-else statements I get a segmentation fault when I run the program.

If I only do this to the step2\_ function where I only keep the “then clause” I get a segmentation fault in the step3\_ function.

How can I keep the entire if-then-else clause of these two functions (step2\_ and step3\_)?

The first segmentation fault occurs on the fourth call to STEP2. The second segmentation fault occurs on the second call to STEP3.

I ask this because if I just keep the “then clause” body (throw away the if condition) and delete the “else clause” in each of these functions I get the same segmentation fault at step 5 which is called from the fourth file called C.f.

In the C code for step2\_, the integer\_adress varial print out as nil on the first three calls but some how is not nil on the fourth call.

I do not know if this code will compile. This pseudo code is to demonstrate the problem.

I tried changing floats to doubles in the C code but the segmentation fault persisted.

If I remove the first three function calls to STEP2 in file A.f the first segmentation fault does not occur. Nothing else in the code appears to be directly causing these faults. I.E.: Nothing else is changing these variables.

If I print out errno after calling malloc it prints out as 0.

The C file is used by the Fortran code via an archive file. The command outputs to create that archive file are:

```auto
cc -g -Wall -Werror -fmax-errors=1 -c -o B.o B.c
r - B.o
ar rvu ../lib.a
ranlib ../lib.a

```

The Fortran files are compiled with the following options:

```auto
-g -fno-second-underscore -Wall -Werror -fmax-errors=1 -fcheck=all

```

----- file A.f ----

```auto
      SUBROUTINE STEP1
      IMPLICIT NONE

      INCLUDE 'STUFF'

      INTEGER STEP2, STEP3

      C = 0
      if (STEP2(C,1).NE.0) print *,'not good'
      E =0
      if (STEP2(E,1).NE.0) print *,'not good'
      F = 0
      if (STEP2(F,1).NE.0) print *,'not good'
      B = 0
      if (STEP2(B,1).NE.0) print *,'not good'
C Program received signal SIGSEGV: Segmentation 
C fault - invalid memory reference.

      G = 0
      if (STEP3(G,1).NE.0) print *,'not good'
      D = 0
      if (STEP3(D,1).NE.0) print *,'not good'
C Program received signal SIGSEGV: Segmentation 
C fault - invalid memory reference.

      RETURN
      END

```

----- file B.c ----

```auto
struct my_data {
   int value;
};

struct my_data2 {
   int value;
};

  int step2_(integer_address,the_one)
  float **integer_address;
  register struct my_data *the_one;
{
    int return_value=0;

    if(!*integer_address)
      *integer_address=(float *)malloc(the_one->num*sizeof(float));
    else
      *integer_address=(float *)realloc(*integer_address,the_one->num*sizeof(float));

    if(!*integer_address)return_value=1;

  return(return_value);
}

  int step3_(integer_address,the_one)
  int **integer_address;
  register struct my_data *the_one;
{
    int return_value=0;

    if(!*integer_address)
      *integer_address=(int *)malloc(MAX(1, the_one->num)*sizeof(int));
    else
      *integer_address=(int *)realloc(*integer_address,MAX(1, the_one->num) *sizeof(int));

    if(!*integer_address)return_value=1;

  return(return_value);
}

  int step5_(dest,src)
  register struct my_data2 **dest,*src;
{
    (*dest)->value=src->value;
    /* Program received signal SIGSEGV: Segmentation fault - invalid memory reference.*/
  return;
}

```

----- file C.f ----

```auto
      SUBROUTINE STEP4(THEADDR)
      INTEGER THEADDR,Z
C ... ... ...
C
C With THEADDR being set to some large value 
C such as 1000000000 (this number is made up)

      DO 10 Z=1,100
       CALL STEP5(THEADDR+Z*4,0)
10 CONTINUE

      RETURN
      END

```

----- file STUFF ----

```auto
      INTEGER A
      
      INTEGER B,
     & C,
     & D,
     & E,
     & F,
     & G
      
      INTEGER H
      INTEGER I

      COMMON/INTEGER_ADDR/H,I,A,D,G
      COMMON/REAL_ADDR/B,C,E,F

```

---

<div class="post-metadata">

**Author:** ![msz59](https://avatars.discourse-cdn.com/v4/letter/m/3d9bf3/32.png) [@msz59](https://fortran-lang.discourse.group/u/msz59)\
**Post date:** [April 4, 2022, 5:56pm UTC](https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128/2 "2022-04-04T17:56:52Z")

</div>

Your code does not compile, A.f and B.c as well. None of your 4 files contain main (PROGRAM) segment. So how can you tell _The program runs perfectly on 32 bit Linux_?

---

<div class="post-metadata">

**Author:** ![gnikit](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/gnikit/32/1213_2.png) [@gnikit](https://fortran-lang.discourse.group/u/gnikit)\
**Post date:** [April 4, 2022, 6:02pm UTC](https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128/4 "2022-04-04T18:02:23Z")

</div>

It can be a bit difficult to understand what is going on if we don’t have access to the full source code. Might I suggest you create a GitHub repo and add the link in this thread.

Assuming you can share the full source code in the first place.

---

<div class="post-metadata">

**Author:** ![msz59](https://avatars.discourse-cdn.com/v4/letter/m/3d9bf3/32.png) [@msz59](https://fortran-lang.discourse.group/u/msz59)\
**Post date:** [April 4, 2022, 6:05pm UTC](https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128/6 "2022-04-04T18:05:38Z")

</div>

It won’t compile even if put into bigger code. In B.c, you use non-existing `my_data` struct’s member `new` (should be `value`). In A.f you use unclassifiable statements like `STEP2(C,1)`. If `STEP2` is a subroutine, must be invoked as `CALL STEP2(C,1)`. If it is a function, it cannot stay alone in the statement (that is possible in C but not in Fortran)

---

<div class="post-metadata">

**Author:** ![mecej4](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/mecej4/32/855_2.png) [@mecej4](https://fortran-lang.discourse.group/u/mecej4)\
**Post date:** [April 4, 2022, 6:25pm UTC](https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128/8 "2022-04-04T18:25:38Z")

</div>

> [@giraffe](#):
>
> `if (STEP2(C,1)) print *,'good'`

This statement is not valid in Fortran unless STEP2 is a function of type LOGICAL, and ‘STUFF’ contains a declaration to that effect. Since STEP2 is implemented as a C function of type integer, your code is invalid and all kinds of things can happen if you manage to build and run an EXE with such faulty code.

---

<div class="post-metadata">

**Author:** ![mecej4](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/mecej4/32/855_2.png) [@mecej4](https://fortran-lang.discourse.group/u/mecej4)\
**Post date:** [April 4, 2022, 6:37pm UTC](https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128/10 "2022-04-04T18:37:56Z")

</div>

> [@giraffe](#):
>
> `if (STEP2(C,1).NE.0) print *,'not good'`

This is still wrong, since STEP2 is considered to be a function of type default REAL, and interpreting an integer value as an IEEE-32 real is probably not meaningful in your application.

---

<div class="post-metadata">

**Author:** ![awvwgk](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/awvwgk/32/154_2.png) [@awvwgk](https://fortran-lang.discourse.group/u/awvwgk)\
**Post date:** [April 4, 2022, 7:53pm UTC](https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128/15 "2022-04-04T19:53:38Z")

</div>

Oh, fun with pointers.

First off, I would highly recommend to use `iso_c_binding` kind parameters and `bind(c)` attributes, as this would allow you to write routines compatible for both 32bit and 64bit Linux. If you use the [`c_intptr_t`](https://en.cppreference.com/w/c/types/integer) from the [`iso_c_binding`](https://gcc.gnu.org/onlinedocs/gfortran/ISO_005fC_005fBINDING.html) module to declare your common block integers you will have enough space to store a 64bit wide pointer address.

The segfault you are observing is most likely a result from attempting to store a pointer address in a default integer (usually 32bit wide), accidentally overwriting adjacent entries in the common block and than later trying to free a completely different location in memory.

You are relying on a lot more platform specifics in the posted example snippets. Getting those sorted provides plenty of learning opportunities, both in C and Fortran ;).

---

<div class="post-metadata">

**Author:** ![awvwgk](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/awvwgk/32/154_2.png) [@awvwgk](https://fortran-lang.discourse.group/u/awvwgk)\
**Post date:** [April 4, 2022, 8:17pm UTC](https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128/17 "2022-04-04T20:17:03Z")

</div>

> [@giraffe](#):
>
> Besides the above C code, how do I fix this in code such as below? What can I try? What are my options? What can you teach me? What will be my indirect problems?
> 
> How can I change my entire program?
> 
> Do you have a good, practical, and intuitive reference on the Internet?

Lot’s of questions. Given that the project is proprietary, have you considered hiring a consultant to fix your code?

The wisdom I can share is the same as above, have a look into C/Fortran interop and declare your interoperable procedures properly.

---

<div class="post-metadata">

**Author:** ![msz59](https://avatars.discourse-cdn.com/v4/letter/m/3d9bf3/32.png) [@msz59](https://fortran-lang.discourse.group/u/msz59)\
**Post date:** [April 4, 2022, 8:46pm UTC](https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128/20 "2022-04-04T20:46:24Z")

</div>

I’m afraid nobody can help you without knowing more about the code being fixed. From the snippets you published, it contains lot’s of errors, including such that are guaranteed to crash in 64-bit. E.g. your `step5_` C-function above is invoked by following Fortran code:

```auto
      INTEGER THEADDR,Z
C ... ... ...
C
C With THEADDR being set to some large value 
C such as 1000000000 (this number is made up)

      DO 10 Z=1,100
       CALL STEP5(THEADDR+Z*4,0)
10 CONTINUE

```

The first argument of the call is `INTEGER` (usually 4-byte) and the offset (at least it looks like an offset) is apparently calculated as `Z*4`, again suggesting 4-bytes/32-bits entities. If you compile that in 64-bits, it just **cannot** work, as the `step5_` function in C interprets its first argument as double pointer, so the values of `THEADDR+Z*4` should be actually pointers (addresses), not integer values. It is unlikely that this can be properly done in Fortran, unless `THEADDR` itself is a pointer somehow imported from another C function. Even so, it is 32-bit value, unable to represent a 64-bit pointer required by `step5_`

---

<div class="post-metadata">

**Author:** ![msz59](https://avatars.discourse-cdn.com/v4/letter/m/3d9bf3/32.png) [@msz59](https://fortran-lang.discourse.group/u/msz59)\
**Post date:** [April 5, 2022, 1:37pm UTC](https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128/23 "2022-04-05T13:37:47Z")

</div>

I did explain, I guess. The integer `THEADDR` is interpreted (by C routine) as an address (pointer). In 32-bit environment, this may work. In 64-bit, you need a 64-bit entity to represent an address/pointer. And `THEADDR` is in typical implementation, 32-bit value both in 32 and 64-bit environment. So in 64-bit env, `spec5_` functions takes 32 bits of the address from `THEADDR+offset` value and other 32 bits from a place in memory with random value.

---

<div class="post-metadata">

**Author:** ![feenberg](https://avatars.discourse-cdn.com/v4/letter/f/c2a13f/32.png) [@feenberg](https://fortran-lang.discourse.group/u/feenberg)\
**Post date:** [April 5, 2022, 1:51pm UTC](https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128/25 "2022-04-05T13:51:52Z")

</div>

valgrind is pretty good at diagnosing segmentation faults.

---

<div class="post-metadata">

**Author:** ![msz59](https://avatars.discourse-cdn.com/v4/letter/m/3d9bf3/32.png) [@msz59](https://fortran-lang.discourse.group/u/msz59)\
**Post date:** [April 5, 2022, 1:58pm UTC](https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128/26 "2022-04-05T13:58:09Z")

</div>

> [@giraffe](#):
>
> I just don’t think that a recent compiler would throw away functionality.

The code is not standard-conforming and uses implementation-specific features, so do not blame the compiler. It is probably _fixable_ by someone knowing the implementation, Fortran and the **whole** code.

BTW, why would you force switching to 64-bit if 32-bit version works. You can run 32-bit applications in 64-bit Linux

---

<div class="post-metadata">

**Author:** ![awvwgk](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/awvwgk/32/154_2.png) [@awvwgk](https://fortran-lang.discourse.group/u/awvwgk)\
**Post date:** [April 5, 2022, 1:59pm UTC](https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128/27 "2022-04-05T13:59:05Z")

</div>

> [@giraffe](#):
>
> There has to be a way. I just don’t think that a recent compiler would throw away functionality. Functionality is almost always added in a new compiler.

Indeed, Fortran compilers will probably never stop supporting standard compliant code and it will be portable across platforms and architectures. However, the shown code snippets are not standard compliant and you are relying on architecture specifics (_e.g._ width of pointer addresses).

The way forward for you would be to make your code standard compliant and replace architecture specific constants and variables. I think all apparent issues in the posted snippets were already spotted and discussed in this thread, including suggestions how to fix them.

> [@giraffe](#):
>
> The question remains. How can someone make the code work?

Sure, someone can probably fix it, might be a bit challenging but certainly not impossible. Not sure if someone will _volunteer_ their time to fix it for you.

---

<div class="post-metadata">

**Author:** ![everythingfunctional](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/everythingfunctional/32/176_2.png) [@everythingfunctional](https://fortran-lang.discourse.group/u/everythingfunctional)\
**Post date:** [April 5, 2022, 2:33pm UTC](https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128/29 "2022-04-05T14:33:41Z")

</div>

“standard compliant” means that all constructs and operations are performed in accordance with the standard. Not all violations of the standard can be identified at compile time. Not to mention if your interfaces “lie” to the compiler.

One of the key violations identified is that you are passing a Fortran `integer` (default integer, which is typically 32 bits), to a C function which expects a pointer (in Fortran `type(c_ptr)`). You either haven’t supplied an explicit interface at the call site, in which case the compiler can’t even check that you are calling it correctly, or have “lied” about what the C interface actually looks like.

This “works” on a 32 bit machine, because in that environment C pointers are actually 32 bit entities. When you move to a 64 bit machine, the pointers are now 64 bit, but you haven’t switched to that on the Fortran side.

The proper fix for this situation is to go carefully define the interfaces to the C procedures on the Fortran side, making sure to use things like `type(c_ptr)`, `integer(kind=c_int)`, etc.

You may also find [my YouTube video](https://youtu.be/z5km039ZVYE) on this topic helpful.

---

<div class="post-metadata">

**Author:** ![ivanpribec](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ivanpribec/32/3290_2.png) [@ivanpribec](https://fortran-lang.discourse.group/u/ivanpribec)\
**Post date:** [April 5, 2022, 3:08pm UTC](https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128/30 "2022-04-05T15:08:17Z")

</div>

> [@giraffe](#):
>
> ```auto
> C With THEADDR being set to some large value 
> C such as 1000000000 (this number is made up)
> 
> DO 10 Z=1,100
> CALL STEP5(THEADDR+Z*4,0)
> 10 CONTINUE
> 
> ```

Concerning this part, I’d also be worried about integer overflow (wraparound) in case `THEADDR` is even larger than you say. Assuming your Fortran compiler defaults to 32-bit integers, the largest value representable is 2147483647.

---

<div class="post-metadata">

**Author:** ![msz59](https://avatars.discourse-cdn.com/v4/letter/m/3d9bf3/32.png) [@msz59](https://fortran-lang.discourse.group/u/msz59)\
**Post date:** [April 5, 2022, 3:13pm UTC](https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128/31 "2022-04-05T15:13:19Z")

</div>

It would also be interesting to know how that `THEADDR` is created/initialized up in the calling sequence (AFAIR it is a dummy argument at this very place) so that it can serve as a pointer in the C function that it is passed (with the offset) as an argument.

---

<div class="post-metadata">

**Author:** ![everythingfunctional](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/everythingfunctional/32/176_2.png) [@everythingfunctional](https://fortran-lang.discourse.group/u/everythingfunctional)\
**Post date:** [April 5, 2022, 9:05pm UTC](https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128/33 "2022-04-05T21:05:17Z")

</div>

> [@giraffe](#):
>
> (C pointers used in the above code and 32 bit integers in the Fortran code)

C pointers and Fortran integers are not the same thing. Using them interchangeably is not standards compliant. You have to go change all the declarations where a variable is used as a C pointer to `type(c_ptr)`.

FYI, I am available for consulting work if you do want actual help working on the code.

---

<div class="post-metadata">

**Author:** ![ivanpribec](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ivanpribec/32/3290_2.png) [@ivanpribec](https://fortran-lang.discourse.group/u/ivanpribec)\
**Post date:** [April 6, 2022, 3:30pm UTC](https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128/35 "2022-04-06T15:30:23Z")

</div>

> [@giraffe](#):
>
> Are there any good books on this topic?
> 
> I would be interested in an entry level and advanced book on the iso\_c\_binding intrinsic module. Specifically, a book or books that explain in nice detail how to use it as a Fortran/C programmer.

My recommendations are

- Metcalf, Reid, Cohen, _Modern Fortran Explained_, Oxford University Press, 2018, or
- Milan Curcic, [_Modern Fortran_](https://www.manning.com/books/modern-fortran), Manning, 2020. (you may be able to get a free preview of chapter 11 on interoperability with C)

> [@giraffe](#):
>
> Are there any advanced explanatory tutorials on the Internet?

- [Interoperability with C](https://gcc.gnu.org/onlinedocs/gfortran/Interoperability-with-C.html), GNU Fortran documentation
- [Interoperation of Fortran with C](https://doku.lrz.de/download/attachments/43320950/Advanced_Fortran_Interop.pdf?version=6&modificationDate=1639680232897&api=v2), Course Notes from the Leibniz Supercomputing Centre

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [April 6, 2022, 7:07pm UTC](https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128/37 "2022-04-06T19:07:45Z")

</div>

Discussing interoperability is on-topic here, but it is difficult to give specific advice without seeing code.

The iso\_c\_binding intrinsic module was introduced in the Fortran 2003 standard. C interoperability is important for Fortran, and all currently maintained compilers should have the module. The definitions of intrinsic procedures and named constants in the module are unlikely to change. When compilers break backward compatibility because the Fortran standard has removed a feature, they have an option to enable the old behavior. For example, gfortran has the -std=legacy option.

---

<div class="post-metadata">

**Author:** ![everythingfunctional](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/everythingfunctional/32/176_2.png) [@everythingfunctional](https://fortran-lang.discourse.group/u/everythingfunctional)\
**Post date:** [April 6, 2022, 9:33pm UTC](https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128/40 "2022-04-06T21:33:46Z")

</div>

This will not work. You do not have an explicit interface for `call_it`. The `implicit none` will probably catch you in this case and the compiler will complain, since it won’t be able to assume the return type of the function. If you add an explicit interface it might work as expected, but the `call_it` function is completely unnecessary in this case. Just call `func` directly.

```auto
SUBROUTINE foobar ()
         interface
           function func(arg) result(res) bind(C, name='func')
             import :: c_int
             integer(c_int), intent(in), value :: arg
             integer(c_int) :: res
           end function
         end interface
         INTEGER(KIND=C_INT) :: i
     
         ! Use it.
         DO i = 1_C_INT, 10_C_INT
           PRINT *, func (i)
         END DO
END SUBROUTINE foobar

```

[Next page](https://fortran-lang.discourse.group/t/on-linux-moving-32-bit-program-to-64-bit-3-segmentation-faults-for-invalid-memory-references-malloc/3128.md?page=2)
