user1220978
user1220978

Reputation:

gfortran optimizer prevents an access violation

The following program tries to do a common mistake: modify a function argument, whereas it is passed initially as a constant. Thus, usually, the constant is stored in a read-only section in object code, and at run time one gets an access violation.

It's exactly what happens with gfortran, with optimization -O0 or -O1 (gfortran 4.8.1 on Windows). But it disappears with -O2, and the second PRINT shows the value 100, like the first.

By inspection of the assembly output, I can see that in the -O1 case, the function F is optimized out, but the computations are still done in the code of A, and storing 117 causes a crash. With -O2, no computation is done, the result (201) is included in the assembly output as a constant, and the value 117 is never stored.

program bob
    implicit none
    call a(100)
contains
    subroutine a(n)
        integer :: n
        print *, "In A:", f(n), n
        print *, n
    end subroutine
    function f(n)
        integer :: n, f
        f = 2*n + 1
        n = 117
    end function
end program

Is this behaviour accepted by the standard? Is this a bug? My first thought was that maybe it's a bug of the optimizer (it does not do something that would have indeed an effect, since the modified value is printed afterwards). But I'm aware that usually, an undefined behaviour in the standard can have any consequence when actually run.

If I replace the constant 100 in the call, with a variable previously initialized to 100, the compiler produces the expected result (the second PRINT gives me 117, with any optimization level).

So, maybe the optimizer is very clever, in the "constant" case: since the code would crash, the print woud not happen, so the value is not needed, so optmized out, and finally the program won't crash. But I still find it a bit puzzling.

Upvotes: 3

Views: 281

Answers (2)

Hristo Iliev
Hristo Iliev

Reputation: 74375

This is probably a bug in the constants propagation module of the GCC optimiser. It is enabled by default for any optimisation level greater than -O1 and could be disabled by passing -fno-ipa-cp.

This example only serves to illustrate the importance of giving each dummy argument the correct INTENT attribute. When n is marked as INTENT(INOUT) in a, the compiler gives an error, no matter what the optimisation level.

Upvotes: 1

IanH
IanH

Reputation: 21431

The behaviour of the erroneous program is consistent with what the standard requires.

The standard doesn't require the compiler to diagnose this particular error (it is not a violation of the numbered syntax rules or numbered constraints). Beyond that, if a program is in error in this way, then the standard doesn't impose any requirements on the Fortran processor.

It does not reveal a bug in the compiler. Any behaviour is valid, including things like the compiler beating you over the head with a stick.

Perhaps you should have stated your INTENT.

Upvotes: 3

Related Questions