There appears to be a memory leak and double deallocation of formatting strings during I/O when a function is used to determine the logical unit number.
I know that i/o list items may not, themselves, be functions that also produce i/o, otherwise recursive i/o problems can occur. However I am not aware of any similar restriction on a function that returns an integer for the
unit= specifier of a write statement.
In the code shown below, the PGI Fortran runtime seems to be doing the following:
- Allocate global pointer for “(A)” format
- Call Run_ErrUnit to determine the logical unit to use
- Allocate global pointer for “('===>…)” format
- Write file, line to output
- Deallocate global pointer
- Write error message
- Deallocate global pointer ! Ooops! not again
Other compilers tested (ifort, gfortran, nagfor) produce the following, correct output:
====> ERROR (macro.F90:26) <==== Error message. ====> ERROR (macro.F90:27) <==== Error message 127.
But pgfortran produces the following:
====> ERROR (macro.F90:26) <==== ====> ERROR ( a.out(94046,0xa17941a8) malloc: *** error for object 0x1050400: pointer being freed was not allocated *** set a breakpoint in malloc_error_break to debug
A second “====> ERROR…” is appearing instead of the error message “Error message.”, indicating the main program write statement is using a stale format from the function call.
It seems the simple solution is for the compiler to reverse the order of #1 and #2 above.
The code used to test this is below (macro.F90):
module Run_Errors integer, save, private :: err_unit = 6 integer, save, private :: warn_unit = 7 integer, save, private :: err_count = 0 contains integer function Run_ErrUnit(file,line) implicit none character(*), intent(in) :: file integer, intent(in) :: line write(err_unit,"(/,'====> ERROR (',A,':',I0,') <====')") file,line if (err_unit /= warn_unit) write(warn_unit,"(/,'====> ERROR (',A,':',I0,') <====')") file,line Run_ErrUnit = err_unit err_count = err_count + 1 return end function end module Run_Errors #define RUN_ERROR(fmt) WRITE(Run_ErrUnit(__FILE__,__LINE__),fmt) program test use Run_Errors RUN_ERROR("(A)") "Error message." RUN_ERROR("('Error: ',i0)") 127 end program