Detecting and Locating Memory Leaks in Fortran Programs
Memory leaks in Fortran can be tricky to find, especially in large codebases. Here are several approaches to detect and locate them:
1. Using Specialized Tools
Valgrind (Linux/Mac)
valgrind --leak-check=full --show-leak-kinds=all ./your_fortran_program
- Works best with
-g
compiler flag for debug symbols - May need
--track-origins=yes
for better tracking - Note: Some false positives may occur with Fortran runtime
Intel Inspector (Windows/Linux)
- Specialized memory leak detection for Fortran
- Provides graphical interface and detailed reports
2. Compiler-Specific Options
gfortran:
gfortran -g -fcheck=all -fbacktrace your_program.f90
Intel Fortran:
ifort -g -check all -traceback your_program.f90
3. Manual Techniques
Allocation/Deallocation Tracking
! Wrap allocations/deallocations with counters
module mem_track
integer, private :: alloc_count = 0, dealloc_count = 0
contains
subroutine track_alloc(size)
integer, intent(in) :: size
alloc_count = alloc_count + size
print *, 'Allocated: ', size, ' Total: ', alloc_count
end subroutine
subroutine track_dealloc(size)
integer, intent(in) :: size
dealloc_count = dealloc_count + size
print *, 'Deallocated: ', size, ' Total: ', dealloc_count
end subroutine
subroutine check_leaks()
if (alloc_count /= dealloc_count) then
print *, 'POTENTIAL MEMORY LEAK: ', alloc_count - dealloc_count
end if
end subroutine
end module
Instrument Your Code
- Add logging around all allocate/deallocate statements
- Use preprocessor macros to enable/disable tracking:
#ifdef DEBUG_MEM
#define ALLOCATE(x,s) allocate(x(s)); call track_alloc(size(x))
#else
#define ALLOCATE(x,s) allocate(x(s))
#endif
4. Runtime Monitoring
Output Array Sizes
! At suspected leak locations
print *, 'Array size check: ', size(suspect_array)
Watch Memory Usage
- Use system tools like
top
,htop
, orps
to monitor memory growth
Common Fortran Leak Sources
- Forgotten DEALLOCATE statements
- Early returns before deallocation
- Exception paths that bypass deallocation
- Circular references in derived types
- Library calls that allocate memory internally
Best Practices
- Always pair ALLOCATE with DEALLOCATE
- Use Fortran 2003+ automatic allocation features where possible
- Consider using allocatable arrays instead of pointers when possible
- Implement module-level cleanup routines
- Use finalizers for derived types (Fortran 2003+)
Would you like more specific information about any of these techniques or particular types of memory leaks you’re encountering?
Appendix
%MEM
top -p <PID> -d 10 -n 10000 -b | tee top.log
grep <USER> top.log | awk '{print $10}'
Caveat
pointer->allocatable,target
grep -i pointer x.f90
grep -i allocate x.f90
grep -i deallocate x.f90
教训
尽可能避免使用pointer,不要用allocate给pointer变量申请内存资源,用allocate,target类型申请资源,需要时可用pointer指向allocate,target变量!