Created attachment 1982609 [details] simple.c Reproducer: $ gcc -c simple.c $ gfortran -g -O0 simple.f -o simple simple.o $ ./simple Operating system error: Cannot allocate memory Memory allocation failure in xrealloc Several minor changes to simple.c workaround the problem, but should be just hiding the problem. $ rpm -q gcc libgfortran gcc-11.3.1-4.3.el9.aarch64 libgfortran-11.3.1-4.3.el9.aarch64 ... Catchpoint 2 (call to syscall mmap), __GI___mmap64 (offset=0, fd=-1, flags=34, prot=3, len=281470681747456, addr=0x0) at ../sysdeps/unix/sysv/linux/mmap64.c:59 59 return (void *) MMAP_CALL (mmap, addr, len, prot, flags, fd, offset); (gdb) bt full #0 __GI___mmap64 (offset=0, fd=-1, flags=34, prot=3, len=281470681747456, addr=0x0) at ../sysdeps/unix/sysv/linux/mmap64.c:59 sc_ret = 0 #1 __GI___mmap64 (addr=addr@entry=0x0, len=len@entry=281470681747456, prot=3, flags=flags@entry=34, fd=fd@entry=-1, offset=offset@entry=0) at ../sysdeps/unix/sysv/linux/mmap64.c:47 sc_ret = <optimized out> _sys_result = <optimized out> _x5tmp = <optimized out> _x4tmp = <optimized out> _x3tmp = <optimized out> _x2tmp = <optimized out> _x1tmp = <optimized out> _x0tmp = <optimized out> _x0 = <optimized out> _x1 = <optimized out> _x2 = <optimized out> _x3 = <optimized out> _x4 = <optimized out> _x5 = <optimized out> _x8 = <optimized out> #2 0x0000fffff7c4e16c in sysmalloc (nb=nb@entry=281470681743888, av=av@entry=0xfffff7d5daf8 <main_arena>) at malloc.c:2424 mm = <optimized out> old_top = <optimized out> old_size = <optimized out> old_end = <optimized out> size = 281470681747456 brk = <optimized out> correction = <optimized out> snd_brk = <optimized out> front_misalign = <optimized out> end_misalign = <optimized out> aligned_brk = <optimized out> p = <optimized out> remainder = <optimized out> remainder_size = <optimized out> pagesize = 4096 tried_mmap = true __PRETTY_FUNCTION__ = "sysmalloc" #3 0x0000fffff7c4efa0 in _int_malloc (av=av@entry=0xfffff7d5daf8 <main_arena>, bytes=bytes@entry=281470681743873) at malloc.c:4274 p = <optimized out> iters = <optimized out> nb = 281470681743888 idx = 127 bin = <optimized out> victim = <optimized out> size = <optimized out> victim_index = <optimized out> remainder = <optimized out> remainder_size = <optimized out> block = <optimized out> bit = <optimized out> map = <optimized out> fwd = <optimized out> bck = <optimized out> tcache_unsorted_count = 0 tcache_nb = <optimized out> tc_idx = 17591917608991 return_cached = <optimized out> __PRETTY_FUNCTION__ = "_int_malloc" #4 0x0000fffff7c4f344 in _int_realloc (av=0xfffff7d5daf8 <main_arena>, oldp=0x421c20, oldsize=528, nb=281470681743888) at malloc.c:4745 newp = <optimized out> newsize = <optimized out> newmem = <optimized out> next = 0x421e30 remainder = <optimized out> remainder_size = <optimized out> __PRETTY_FUNCTION__ = "_int_realloc" nextsize = <optimized out> #5 0x0000fffff7c506e4 in __GI___libc_realloc (oldmem=0x421c30, bytes=281470681743872) at malloc.c:3352 ar_ptr = 0xfffff7d5daf8 <main_arena> nb = 281470681743888 newp = <optimized out> oldp = 0x421c20 oldsize = 528 __PRETTY_FUNCTION__ = "__libc_realloc" #6 0x0000fffff7e592e4 in _gfortrani_xrealloc (ptr=<optimized out>, size=size@entry=281470681743872) at ../../../libgfortran/runtime/memory.c:92 newp = <optimized out> #7 0x0000fffff7f57c5c in _gfortrani_fbuf_alloc (u=0x421870, len=281470681743366) at ../../../libgfortran/io/fbuf.c:123 newlen = 281470681743872 dest = <optimized out> #8 0x0000fffff7f4a304 in _gfortrani_write_block (dtp=dtp@entry=0xffffffffea78, length=<optimized out>) at ../../../libgfortran/io/transfer.c:855 dest = <optimized out> #9 0x0000fffff7f525d8 in write_character (dtp=dtp@entry=0xffffffffea78, source=source@entry=0xffffffffecf0 "World!", kind=kind@entry=1, length=length@entry=281470681743366, mode=mode@entry=1) at ../../../libgfortran/io/write.c:1416 extra = <optimized out> p = <optimized out> d = <optimized out> #10 0x0000fffff7f56b6c in list_formatted_write_scalar (dtp=dtp@entry=0xffffffffea78, type=type@entry=BT_CHARACTER, p=0xffffffffecf0, kind=kind@entry=1, size=size@entry=281470681743366) at ../../../libgfortran/io/write.c:1900 No locals. #11 0x0000fffff7f579e4 in _gfortrani_list_formatted_write (dtp=0xffffffffea78, type=BT_CHARACTER, p=<optimized out>, kind=1, size=281470681743366, nelems=1) at ../../../libgfortran/io/write.c:1972 elem = 0 tmp = <optimized out> stride = 281470681743366 #12 0x000000000040098c in simple (one=1, two=2, ts1=..., ts2=<error reading variable: value requires 281470681743366 bytes, which is more than max-value-size>, three=3, four=4, five=5, _ts1=7, _ts2=281470681743366) at simple.f:5 No locals. #13 0x0000000000400c44 in main () at simple.c:27 teststring1 = "Hello, \000P\355\377\377\377\377\000\000`\227\276\367\377\377\000", <incomplete sequence \310> teststring2 = "World!\000\000@\344\376\367\377\377", '\000' <repeats 18 times>, "\060\000\000\000\000\000\000\000\377\377\377\377\000\000\000\000\000" one = 1 two = 2 three = 3 four = 4 five = 5 six = 6 clen1 = <optimized out> clen2 = <optimized out> flen1 = 7 flen2 = 6 B3 = {clen = 1, flen = 65535, teststring = 0x0} B4 = {clen = 0, flen = 0, teststring = 0x2f8 <error: Cannot access memory at address 0x2f8>} ...
Created attachment 1982610 [details] simple.f
This really looks like a user error to me. With GCC 13 I get: $ gfortran -Wall -O2 -flto simple.? […] simple.c:26:15: warning: type of ‘simple_’ does not match original declaration [-Wlto-type-mismatch] 26 | extern void simple_(int* one, int* two, char* A, char *B, int* three, int* four, int* five, unsigned _A_len, unsigned _B_len); | ^ simple.f:1:23: note: type mismatch in parameter 8 1 | SUBROUTINE SIMPLE(ONE,TWO,TS1,TS2,THREE,FOUR,FIVE) | ^ simple.f:1:23: note: type ‘long int’ should match type ‘unsigned int’ simple.f:1:23: note: ‘simple’ was previously declared here simple.f:1:23: note: code may be misoptimized unless ‘-fno-strict-aliasing’ is used Fixing simple.c as indicated to: extern void simple_(int* one, int* two, char* A, char *B, int* three, int* four, int* five, long _A_len, long _B_len); This results in a working binary: FORTRAN Teststrings:Hello, World! FORTRAN Teststrings length: 7 6 1 2 3 4 5
The problem is that the system compiler "works" with several minor changes, like just commenting the line: fstring B3, B4; in simple.c, or changing the types of fstring from unsigned int to unsigned long, the warning from gcc 13 now, and several other tests, so, it might be a genuine bug, as several minor changes the sources causes it work.
As documented in https://gcc.gnu.org/gcc-8/changes.html#fortran , the Fortran ABI has changed in GCC 8. In particular for this, "Character variables longer than HUGE(0) elements are now possible on 64-bit targets. Note that this changes the procedure call ABI for all procedures with character arguments on 64-bit targets, as the type of the hidden character length argument has changed. The hidden character length argument is now of type INTEGER(C_SIZE_T)." So, using unsigned for character lengths is incorrect on 64-bit architectures like aarch64. On some architectures you can be lucky and have the upper 32 bits of the 64-bit argument zero and it will appear to "work", but that is clearly not the case here.
For AArch64, the PCS says: “ C.16 If the size of the argument is less than 8 bytes then the size of the argument is set to 8 bytes. The effect is as if the argument was copied to the least significant bits of a 64-bit register and the remaining bits filled with unspecified values. ” <https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#682parameter-passing-rules> So it's indeed not expected to work, and you just get random uninitialized memory (which is why tiny changes make a difference).
In particular, it was the https://gcc.gnu.org/PR78534 https://gcc.gnu.org/r8-5772 change.
(In reply to Jakub Jelinek from comment #4) > As documented in https://gcc.gnu.org/gcc-8/changes.html#fortran , the > Fortran ABI has changed in GCC 8. > In particular for this, > "Character variables longer than HUGE(0) elements are now possible on 64-bit > targets. Note that this changes the procedure call ABI for all procedures > with character arguments on 64-bit targets, as the type of the hidden > character length argument has changed. The hidden character length argument > is now of type INTEGER(C_SIZE_T)." > So, using unsigned for character lengths is incorrect on 64-bit > architectures like aarch64. On some architectures you can be lucky and have > the upper 32 bits of the 64-bit argument zero and it will appear to "work", > but that is clearly not the case here. Thanks. Heuristically this was a guess: (gdb) p (int)281470681747456 $1 = 4096 and the linked document makes it clear.