We have a strange issue with our code, we used a same code since several years on several platforms, but this year we needed to build our software on a 64-bit RHEL 8 system.
During build processing, we need to convert some F77 code to C code using f2c tools.
During this convert processing some variables in memory are defined like this in the output C file.
#define v_hhdcb__ ((shortint *)&dovit_1 + 1608) /* works perfectly */
#define v_cncal__ ((integer *)(&dovit_1 + 5)) /* dovit_1 is a an array of short /*
On all of our systems (HP-UX, AIX,Ubuntu, openSUSE) we obtain the good value when we build C code with GCC.
On Opensuse : The read v_cncal
value is on dovit_1
address + 5 x short type size (2) == >
(10)
But on RHEL the same C code return a bad address value:
On RHEL 8 : The read v_cncal
value is at dovit_1
address + 5 x int type size (4) ==> (20) but dovit_1
is a short
array and not an int
array.
GCC version in both case 8.4 and same f2c compiler
What could be wrong?
UPDATE
During our debugging, we tried to modify manually C code like this :
#define v_cncal__ ((integer *)(&dovit_1 + 5*sizeof(shortint))) /* works */
But this C code is generated by f2c, I think the best way is to ask f2c dev team to known what's happening.
UPDATE 1
How dovit_1 is declared :
/* testdyF.f -- translated by f2c (version 20181026).
You must link the resulting object file with libf2c:
on Microsoft Windows system, link with libf2c.lib;
on Linux or Unix systems, link with .../path/to/libf2c.a -lm
or, if you install libf2c.a in a standard place, with -lf2c -lm
-- in that order, at the end of the command line, as in
cc *.o -lf2c -lm
Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
http://www.netlib.org/f2c/libf2c.zip
*/
union {
struct {
shortint dovita[1];
} _1;
struct {
doublereal eqv_pad[1];
} _2;
} dovit_;
#define dovit_1 (dovit_._1)
#define dovit_2 (dovit_._2)
/* Table of constant values */
static integer c__9 = 9;
static integer c__1 = 1;
static integer c__2 = 2;
static integer c__3 = 3;
shortint *__dovit;
#undef dovit_1
#define dovit_1 __dovit[0]
/* CCCC Tag pour ajout routine d attachement shm */
#include <SHM_INIT.c>
/* _SHM_INIT */
/* Main program */ int MAIN__(void)
{
/* Builtin functions */
integer s_wsle(cilist *), do_lio(integer *, integer *, char *, ftnlen),
e_wsle(void);
/* Local variables */
#define v_pc__ ((shortint *)&dovit_1 + 288100)
#define v_cp__ ((shortint *)&dovit_1 + 288169)
#define v_ct__ ((shortint *)&dovit_1 + 294500)
...
It is Undefined Behaviour as it violates the strict-aliasing rules. when you dereference the
integer *
(I believe that it isint *
)And the result is one of the most common way how UBs "work" - getting the different results using different compilers on when run on different platforms.