Behavior with "negative" reference to character

I am not sure if what I’m describing below is a bug, or a different opinion of the Fortran standard, or what, but I thought I’d ask about it here. If nothing else, maybe I could request PGI change their error reporting.

Namely, a program recently failed with an odd error:

0: ALLOCATE: 18446744073709551615 bytes requested; not enough memory

It only ever failed on PGI; Intel passed it just fine. After some quite laborious stepping through a program with Totalview, the problem was found to be due to referencing a character string with a negative index. An example reproducer is below:

program test

implicit none

character(len=128) :: tmp, argl, argr, expr
integer :: pos 

expr = '12345'
tmp = trim(expr)

!pos = 3
pos = 0 

argl= adjustl(tmp(:pos-1))
argr= adjustl(tmp(pos+1:))

write (*,*) 'tmp:  ',tmp
write (*,*) 'argl: ',argl
write (*,*) 'argr: ',argr

end program test

If you run this with ‘pos=3’ above, it does what you expect:

> ./a.out

Now, try it with ‘pos = 0’ and:

> ./a.out
0: ALLOCATE: 18446744073709551615 bytes requested; not enough memory

So, the issue is evaluating:

argl= adjustl(tmp(:-1))

Obviously, this isn’t something you want to do. The reason this code ever worked on Intel (V 11) is because Intel has a different behavior. If ‘pos=0’ then:

> ./a.out 

It is this behavior the program was expecting. Likewise with gfortran (v 4.1.2):

> ./a.out
 tmp:  12345                                                                                                                           
 argr: 12345

So, I guess I’m asking one of two things:

  • Which behavior is correct according to the standard? That is, should we expect a compiler to behave like Intel or like PGI?
  • If PGI is correct, is it possible to get a more descriptive error with this? Under Totalview (with -g), the program doesn’t actually trigger anything, but just exits out. It’s hard to debug when the debugger doesn’t see this as an issue.


Just a note that the same error:

0: ALLOCATE: 18446744073709551615 bytes requested; not enough memory

is thrown if you do all of the above with an integer array instead, i.e.:

pos = 0

itmp = [1,2,3,4,5]

iargl = -99999
iargr = -99999

iargl(:pos-1) = itmp(:pos-1)
iargr(pos+1:) = itmp(pos+1:)

write (*,*) 'itmp:  ',itmp
write (*,*) 'iargl: ',iargl
write (*,*) 'iargr: ',iargr

gfortran throws:

 itmp:             1           2           3           4           5
 iargl:       -99999      -99999      -99999      -99999      -99999
 iargr:            1           2           3           4           5

I’m beginning to suspect the standard doesn’t say what to do in these situations, so it’s the vendor’s/implementer’s choice…

Hi Matt,

Thanks for narrowing this down. It does look like a compiler error in that it should be checking for the case where the ending position is less then the starting. The length should be set to 0 here but it looks like we’re passing a negative value when allocating the temp string.

I’ve submitted a problem report (TPR#18608) and sent it off to Engineering. We’ve missed the cut-off for 12.4 so I requested this be fixed by the 12.5 release.

Thanks again for the great example.

  • Mat