Недавно я наткнулся на странное поведение в моем коде, где при изменении данных-членов полиморфного пользовательского типа значения других членов данных были изменены. Я пытался применять Valgrind распутать то, что явно казалось памятью, связанные с ошибкой, и нашел несколько ошибок: Conditional jump or move depends on uninitialized value(s)
Почему valgrind сообщает неинициализированные значения в моем полиморфном типе?
После дальнейшего исследования, полиморфные элементы данных возвращаются этой ошибкой, даже если они были явно инициализируются непосредственно перед. Когда я ссылаюсь на индексы в начале выделенного массива var(1)
или неявно индексирует массив с var(:)
, проблем нет, но явно ссылающиеся на элементы в конце массива возвращают ошибку Valgrind. Например:
module particles
implicit none
private
public :: particleArray,initParticles,&
FULLY_KINETIC,DRIFT_KINETIC
integer,parameter :: &
FULLY_KINETIC=1,&
DRIFT_KINETIC=2
type particle
real :: x ! position
end type particle
type, extends (particle) :: particle_dk
real :: vpara ! parallel velocity
end type particle_dk
type, extends (particle) :: particle_fk
real :: vx,vy ! x,y velocity
end type particle_fk
type particleArray
private
class(particle),dimension(:),allocatable :: p
end type
contains
subroutine initParticles(pArray,iParticleType)
type(particleArray),intent(out),target :: pArray
integer,intent(in) :: iParticleType ! flag for FK vs. DK particles
integer :: i,nparticles
nparticles=10
select case (iParticleType)
case (FULLY_KINETIC)
write(*,*)' Particles are FULLY KINETIC.'
allocate(particle_fk::pArray%p(nparticles))
case (DRIFT_KINETIC)
write(*,*)' Particles are DRIFT KINETIC.'
allocate(particle_dk::pArray%p(nparticles))
case default
write(*,*)'ERROR: Requested iParticleType not found.'
stop
end select
! initialize ALL particle array values
pArray%p(:)%x = 0.0
select type (pa => pArray%p)
class is (particle_dk)
pa(:)%vpara = 0.0
class is (particle_fk)
pa(:)%vx = 0.0
pa(:)%vy = 0.0
end select
! modify initialized value
! low indices are fine
pArray%p(1:4)%x = max(pArray%p(1:4)%x,1.0e-6)
! so is this!
pArray%p(:)%x = max(pArray%p(:)%x,1.0e-6)
! ERROR HERE
! but explicit indices near end of allocated array cause
! 'uninitialized' error in valgrind
pArray%p(nparticles)%x = max(pArray%p(nparticles)%x,1.0e-6)
end subroutine initParticles
end module particles
program test
use particles
type(particleArray) :: ions_dk,ions_fk
call initParticles(ions_dk,DRIFT_KINETIC)
call initParticles(ions_fk,FULLY_KINETIC)
end program test
Valgrind возвращается ...
[email protected]:~/memory_bug> valgrind ./test
==16108== Memcheck, a memory error detector
==16108== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==16108== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==16108== Command: ./test
==16108==
--16108-- run: /usr/bin/dsymutil "./test"
Particles are DRIFT KINETIC.
==16108== Conditional jump or move depends on uninitialised value(s)
==16108== at 0x100001B8B: __particles_MOD_initparticles (particles.F90:69)
==16108== by 0x100000FE9: MAIN__ (main.F90:6)
==16108== by 0x100001035: main (main.F90:2)
==16108==
Particles are FULLY KINETIC.
==16108== Conditional jump or move depends on uninitialised value(s)
==16108== at 0x100001B8B: __particles_MOD_initparticles (particles.F90:69)
==16108== by 0x100000FFC: MAIN__ (main.F90:7)
==16108== by 0x100001035: main (main.F90:2)
==16108==
==16108==
==16108== HEAP SUMMARY:
==16108== in use at exit: 22,223 bytes in 191 blocks
==16108== total heap usage: 280 allocs, 89 frees, 34,316 bytes allocated
==16108==
==16108== LEAK SUMMARY:
==16108== definitely lost: 0 bytes in 0 blocks
==16108== indirectly lost: 0 bytes in 0 blocks
==16108== possibly lost: 2,064 bytes in 1 blocks
==16108== still reachable: 200 bytes in 2 blocks
==16108== suppressed: 19,959 bytes in 188 blocks
==16108== Rerun with --leak-check=full to see details of leaked memory
==16108==
==16108== For counts of detected and suppressed errors, rerun with: -v
==16108== Use --track-origins=yes to see where uninitialised values come from
==16108== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Похоже, что какая-то несоответствие между ожидаемым размером за единицу в pArray%p
, когда выделяется nparticles
и позже, когда ссылки с nparticles
. Мои операторы распределения формы allocate(particle_fk::pArray%p(nparticles))
основаны на IBM compiler documentation, так как я не мог найти то же самое для gfortran, что я использую для компиляции. Я неправильно распределяю/ссылаюсь или это функция Fortran 2003, которая неправильно реализована в GCC?
Это похоже на фиктивное предупреждение. Sanitizations ничего не находят, и ваш код выглядит нормально. Я просто использовал бы 'p%' вместо 'p (:)%', но это стиль. –
Стоит попробовать другие версии GCC. Какую версию вы используете? –
Если я инициализирую pArray% p (:)% x, para, vx, vy с, скажем, 1, 10, 20, 30 и распечатаю содержимое позже, gfortran-6.1 и ifort16 дают разные результаты ... hmm (но мой модификация может быть неправильной). – roygvib