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