chw21
chw21

Reputation: 8140

SEGFAULT disappears with lower optimisation level?

So, I want to help my researchers a bit with debugging Fortran programs, and for demonstration purposes I created a program that intentionally causes a segfault.

Here's the source:

program segfault

  implicit none
  integer :: n(10), i
  integer :: ios, u

  open(newunit=u, file='data.txt', status='old', action='read', iostat=ios)
  if (ios /= 0) STOP "error opening file"
  i = 0
  do
    i = i + 1
    read(u, *, iostat=ios) n(i)
    if (ios /= 0) exit
  end do
  close(u)

  print*, sum(n)

end program segfault

The data.txt file contains 100 random numbers:

for i in {1..100}; do 
    echo $RANDOM >> data.txt; 
done

When I compile this program with

gfortran -O3 -o segfault.exe segfault.f90

the resulting executable dutifully crashes. But when I compile with debugging enabled:

gfortran -O0 -g -o segfault.exe segfault.f90

Then it reads in only the first 10 values, and prints their sum. For what it's worth, -O2 causes the desired segfault, -O1 does not.

I find this deeply concerning. After all, how can I debug properly if the bug goes away when I compile with debugging symbols enabled?

Can someone explain this behaviour?

I am using GNU Fortran (MacPorts gcc5 5.3.0_1) 5.3.0

Upvotes: 1

Views: 62

Answers (1)

A segfault is an undefined behaviour. The program does not conform to the Fortran standard so you cannot expect any particular outcome. It can do anything at all. You cannot count with a segfault to happen, the less be deeply concerned whent it does not happen.

There are compiler checks (fcheck=) and sanitizations (-fsanitize=) available for a reason. Waiting for a segfault is not guaranteed to work. Not in Fortran, not in C, not in any similar language.

The outcome of a non-conforming program may depend on many things like placement of a variable in memory or in a register. Aligning of variables in memory, position of stack frames... You can't count with anything at all. These details obviously depend on the optimization level.

If the program accesses an array out of bounds, but the address in memory happens to be a part of memory which still belongs to the process, a segfault may not happen. It is just some bytes in memory which the process is allowed to read or write to (or both). You may be overwriting some other variable, you may be reading some garbage from some old stack frame, you may be overwriting malloc's internal book-keeping data and currupting the heap. The crash may be waiting to happen somewhere else or maybe just the numeric result of the program will be slightly wrong. Anything can happen.

Upvotes: 3

Related Questions