Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

double free or corruption with private pointer and OpenMP parallel do

Ines_F_
Beginner
1,754 Views

Hi all,

I'm having a double free or corruption problem when trying to use the Reallocate function (from Fortran 90 Numerical Recipes) within an OpenMP parallel do directive

*** glibc detected *** ./myprog: double free or corruption (out): 0x00007ffdf7d770f0 ***

Here is the reallocate function :

FUNCTION reallocate_iv(p,n)
    INTEGER(I4B), DIMENSION(:), POINTER :: p, reallocate_iv
    INTEGER(I4B), INTENT(IN) :: n
    INTEGER(I4B) :: nold,ierr
    allocate(reallocate_iv(n),stat=ierr)
  
    if (ierr /= 0) call &
	nrerror('reallocate_iv: problem in attempt to allocate memory')
    if (.not. associated(p)) RETURN
	nold=size(p)
  
    reallocate_iv(1:min(nold,n))=p(1:min(nold,n))
    deallocate(p)
END FUNCTION reallocate_iv

and here is the main body of the code calling reallocate within an OpenMP parallel do directive :

Integer, Dimension(:), POINTER :: col_sprZ
Integer :: nnz, size,spr_perc,spr_size

!$OMP PARALLEL PRIVATE (size,spr_size,,col_sprZ,nnz) 
!$OMP DO SCHEDULE(DYNAMIC)
do kk=1,NB
      spr_size = nint((spr_perc*9.*size**2.)/100.)
      Allocate(col_sprZ(spr_size));
      !! here Call a Subroutine which calculates nnz and col_sprZ (sparse format storage)   
      col_sprZ => Reallocate(col_sprZ,nnz);            
      - - - - - - - - - - - - -                
      Deallocate(col_sprZ);
enddo
!$OMP END DO
!$OMP END PARALLEL

The code works perfectly and yields good results if I discard/comment the OpenMP directive or compile with the -O0 -openmp  -heap arrays. It works also fine if I keep the openmp directive and compile with -O3 -openmp -heap arrays but use a classic temporary allocatable array to reallocate col_sprZ instead of the reallocate function.

I also noticed that the problem could disappear if I decrease the size of the array col_sprZ. I haven't the required authorization to check if the problem is caused by the stack size limits.

I am using intel composer 13.1.3 on Linux.

Did anyone understand or see the cause of this problem ? Thanks !

0 Kudos
7 Replies
jimdempseyatthecove
Honored Contributor III
1,754 Views

Try this:

Prior to the parallel region, nullify col_sprZ
on the $omp parallel statement, identify col_sprZ as firstprivate (this is to copy in the NULLed pointer)
Following the Deallocate(col_sprZ), nullify col_sprZ

I cannot say that this will fix your problem (you have a rather old version of Fortran), the changes above make the program more conforming to the standard.

Jim Dempsey
 

0 Kudos
Ines_F_
Beginner
1,754 Views

Thank your for taking the time to answer my question !

I tried what recommended and I got this :

forrtl: severe (174): SIGSEGV, segmentation fault occurred
Image              PC                Routine            Line        Source             
myprog             00000000004BC379  nrutil_mp_realloc         219  nrutil.f90

The segmentation fault occurs from the beginning in the reallocate function here :

reallocate_iv(1:min(nold,n))=p(1:min(nold,n))

I checked nold and n and they correspond well to the initial/old size of p and the new size (nnz). So I don't really see what causes this segmentation fault. I increased the stack size limit : ulimit -s 2048 but I didn't change anything.

When I keep the nullify before and inside the parallel region, but I declare the pointer as PRIVATE and not FIRSTPRIVATE, I have

glibc detected *** ./myprog: munmap_chunk(): invalid pointer: 0x00002ae5e6b8bcc0

But the code runs longer, it seems to crash when leaving the do loop ! But I haven't any information about the line causing the problem. When I compile with -O3 -openmp -check all -traceback -heap-arrays, I of course loose the optimization (disabling optimization; runtime debug checks enabled) and the code runs perfectly and give accurate results ! so I haven't any further information about the 'munmap_chunk(): invalid pointer' problem.

 Would you have any other suggestion ?  

Thanks !

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,754 Views

>>But the code runs longer, it seems to crash when leaving the do loop

Verify this by something like:

...
!$OMP END DO
print *,omp_get_thread_num()
!$omp barrier
!$omp master
print *,"exiting region"
!$omp end master
!$OMP END PARALLEL
print *,"out of region"

This may be a case where the problem lies with code not shown (-  -  -  -).

Jim Dempsey

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,754 Views

Also as an aid:

!$OMP PARALLEL DEFAULT(NONE), PRIVATE (size,spr_size,,col_sprZ,nnz) 

** then specifically add , SHARED(...) for those you know can be shared and won't be reallocated while running the parallel region.

Jim Dempsey

0 Kudos
Ines_F_
Beginner
1,754 Views

I accidentally removed the subroutine, and when I modified a previous version very quickly, the code ran perfectly with the reallocate function the -O3 debug option and the OpenMP directive !!! 

The only difference I noticed is a certain M=3*size inside the parallel region, which I used to avoid repeating 3*size each time I need it (see code below) ! I checked by using M=3*size again and the code crashes. I don't understand exactly what was the problem, since M is declared as private and used also later in the same do loop, but I think that NULLIFY did the biggest part of the job. Many thanks for your help !

Allocate(Zspr(spr_size),row_sprZ(3*size+1),col_sprZ(spr_size));  
Call SR_Green_s_tr(size,Cells,spr_size,sameEps,nnz,Zspr,row_sprZ,col_sprZ)
            
Zspr => reallocate(Zspr,nnz);
col_sprZ => reallocate(col_sprZ,nnz);
             
iparm3 = 0; ! here iparm3 is not used
Call pardiso_solver(3*size,2*Nb,nnz,mtype,iparm3,row_sprZ,col_sprZ,Zspr,ER,E) 
Deallocate(Zspr,row_sprZ,col_sprZ);
NULLIFY(Zspr,row_sprZ,col_sprZ);

Ines

0 Kudos
Ines_F_
Beginner
1,754 Views

Finally I think that what solved the problem, in addition to NULLIFY is that I increased the stack size limit to 2048 (ulimit -s 2048). 

Thanks !

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,754 Views

>>The only difference I noticed is a certain M=3*size inside the parallel region, which I used to avoid repeating 3*size each time I need it

Perhaps M was unexpectedly modified after being set. Note: call Something(M,...) may potentially modify M whereas trashing the expression argument would do no harm.

Glad you are working.

Jim Dempsey

0 Kudos
Reply