2016-10-28 7 views
1

Недавно я наткнулся на странное поведение в моем коде, где при изменении данных-членов полиморфного пользовательского типа значения других членов данных были изменены. Я пытался применять 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?

+0

Это похоже на фиктивное предупреждение. Sanitizations ничего не находят, и ваш код выглядит нормально. Я просто использовал бы 'p%' вместо 'p (:)%', но это стиль. –

+0

Стоит попробовать другие версии GCC. Какую версию вы используете? –

+0

Если я инициализирую pArray% p (:)% x, para, vx, vy с, скажем, 1, 10, 20, 30 и распечатаю содержимое позже, gfortran-6.1 и ifort16 дают разные результаты ... hmm (но мой модификация может быть неправильной). – roygvib

ответ

0

Я попробовал более простую версию программы OP с разными начальными значениями для x и т. Д. (1,2,3,4).

module particle_mod 
    implicit none 

    type particle 
     real :: x 
    endtype 

    type, extends(particle) :: particle_1 
     real :: vp 
    endtype 

    type, extends(particle) :: particle_2 
     real :: vx,vy 
    endtype 

    type particleArray 
     class(particle), allocatable :: p(:) 
    endtype 

contains 
    subroutine initParticles(pArray, itype) 
     type(particleArray), intent(out) :: pArray 
     integer, intent(in) :: itype 
     integer :: nparticles 
     character(20) :: fmt 

     nparticles = 6 

     select case (itype) 
     case (1) 
      print "(/,a)", "allocating type 1" 
      allocate(particle_1 :: pArray % p(nparticles)) 
     case (2) 
      print "(/,a)", "allocating type 2" 
      allocate(particle_2 :: pArray % p(nparticles)) 
     end select 

     ! initialize all values 
     pArray % p(:) % x = 1.0 

     select type (pa => pArray % p) 
     class is (particle_1) 
      pa(:) % vp = 2.0 
     class is (particle_2) 
      pa(:) % vx = 3.0 
      pa(:) % vy = 4.0 
     end select 

     ! print the values 
     fmt = "(a, *(f5.1, x))" 
     print fmt, "x = ", pArray % p(:) % x 

     select type (pa => pArray % p) 
     class is (particle_1) 
      print fmt, "type1 : x = ", pa(:) % x 
      print fmt, "type1 : vp = ", pa(:) % vp 
     class is (particle_2) 
      print fmt, "type2 : x = ", pa(:) % x 
      print fmt, "type2 : vx = ", pa(:) % vx 
      print fmt, "type2 : vy = ", pa(:) % vy 
     end select 

    end subroutine 
end module 

program test 
    use particle_mod 
    implicit none 
    type(particleArray) :: ions_1, ions_2 

    call initParticles(ions_1, 1) 
    call initParticles(ions_2, 2) 
end program 

Затем, если эта программа составлена ​​с gfortran-6.1, это дает следующий результат:

allocating type 1 
x = 1.0 2.0 1.0 2.0 1.0 2.0 
type1 : x = 1.0 1.0 1.0 0.0 0.0 0.0 
type1 : vp = 2.0 2.0 2.0 2.0 2.0 2.0 

allocating type 2 
x = 1.0 3.0 4.0 1.0 3.0 4.0 
type2 : x = 1.0 1.0 0.0 0.0 0.0 0.0 
type2 : vx = 3.0 3.0 3.0 3.0 3.0 3.0 
type2 : vy = 4.0 4.0 4.0 4.0 4.0 4.0 

Но выход х (:) кажется странным ... (я ожидал, что это укажите 1.0 1.0 ... 1.0). Я не могу получить доступ к ifort прямо сейчас, поэтому было бы полезно попробовать эту программу также с ifort.

+0

Я не очень уверен, что указанная выше программа верна, поэтому я был бы признателен, если вы найдете странную точку. – roygvib

+0

Кажется, что когда 'pArray% p (:)% x' обращается за пределами' select type 'block, память неправильно обращается, как если бы унаследованные переменные не существовали, т. е.' pArray% p' рассматривается как тип, а не класс. – oghma

+0

[Теперь я получил доступ к ifort и oracle fortran и т. Д., Я попробую подобные шаблоны, если они дадут одинаковые или разные результаты (в зависимости от компиляторов) и проведут проверку синтаксиса. Я все еще не очень понимаю это синтаксическое поведение ...] – roygvib