2012-05-03 3 views
0

시뮬레이션 소프트웨어를 충돌시키는 segfault/sigabort를 디버깅하려고했습니다. 나는이 LAPACK 서브 루틴을 (또는 실제로 할당을 해제하고, 나는 생각한다) 서브 루틴의 그리드 카운터를 변경하여 특정 LAPACK 서브 루틴으로 추적 할 수 있었다 (다른 몇 가지 서브 루틴을 통해)이 LAPACK 서브 루틴을 호출한다.dlatrs 서브 루틴이 호출 서브 루틴에서 카운터를 할당 해제합니다.

(gdb) break trifactorize 
Breakpoint 1 at 0x44ad28: file /home/nspeelman/chem1d/src/solver.f, line 925. 
(gdb) run 
Starting program: /home/nspeelman/chem1d/bin/chem1d 

(gdb) watch k 
Hardware watchpoint 2: k 
(gdb) c 
Continuing. 
Hardware watchpoint 2: k 

Old value = 4 
New value = 1 
0x000000000044ad48 in trifactorize ([email protected]) at /home/nspeelman/chem1d/src/solver.f:927 
927   DO k = 1, Npoint 
(gdb) c 
Continuing. 
Hardware watchpoint 2: k 

Old value = 1 
New value = -214061846 
dlatrs ([email protected], [email protected], [email protected], [email protected], [email protected], a=0x16867060, 
    [email protected], x=0x7fffffffcf90, [email protected], cnorm=0x7fffffffd910, [email protected], _uplo=5, 
    _trans=12, _diag=4, _normin=1) at /home/nspeelman/chem1d/src/lapack/src/dlatrs.f:334 
334     DO 20 J = 1, N - 1 
(gdb) c 
Continuing. 

Program received signal SIGABRT, Aborted. 
0x00002aaaab480265 in raise() from /lib64/libc.so.6 

그리고 역 추적 : 내가 gfortran 4.6 gfortran 4.6.1, 우분투 12.04 우분투 11.10으로 재현 할 수있었습니다

(gdb) bt 
#0 0x00002aaaab480265 in raise() from /lib64/libc.so.6 
#1 0x00002aaaab481d10 in abort() from /lib64/libc.so.6 
#2 0x00002aaaaad88c9e in internal_unpack (d=0x62e9, s=0x62e9) 
    at ../../../gcc-4.3.4/libgfortran/runtime/in_unpack_generic.c:104 
#3 0x000000000044b41c in trifactorize ([email protected]) at /home/nspeelman/chem1d/src/solver.f:940 
#4 0x3f68b52055ec1bbd in ??() 
#5 0x3f62d2224f8b7801 in ??() 
#6 0x3f62e59e02e2572f in ??() 
#7 0x3f70bab1bd0628c7 in ??() 
#8 0x3f70cdc893daf1cf in ??() 
#9 0x3f5a3418697ab4dc in ??() 
#10 0x3f6b117db1893c97 in ??() 
#11 0x3f6e0dd1b55652b4 in ??() 
#12 0x3f6864101f64d2f0 in ??() 
#13 0x3f7359216186a4dc in ??() 
#14 0x3f527ee1ff8feb69 in ??() 
#15 0x3f672c7c504a10f8 in ??() 
#16 0x3f68f2c8e0ee6963 in ??() 
#17 0x3f54726715d81583 in ??() 
#18 0x3f68f2c8e0ee6963 in ??() 
#19 0x3f6df6a7d0f5e9a5 in ??() 
#20 0x3f5ef57fdf747822 in ??() 
#21 0x3f56ef95d71519b0 in ??() 
#22 0x3f6b736cc1c1feb4 in ??() 
#23 0x3f60fb91d9400ca4 in ??() 
#24 0x3f56ef95d71519b0 in ??() 
#25 0x3f4b4753f00f24d5 in ??() 
#26 0x3f5a8b9cc465a316 in ??() 
#27 0x3f3855b423b18a6b in ??() 
#28 0x3f568360294ec05f in ??() 
#29 0x3f3679d6e42a4759 in ??() 
#30 0x3f228fe18a3e97ab in ??() 
#31 0x3f50df603cf17c50 in ??() 
#32 0x3f5d0cea5690c8f8 in ??() 
#33 0x3f550552679170e1 in ??() 
#34 0x3f3d0ebaa18f7a6f in ??() 
#35 0x3f66a1b9ef4a7dc4 in ??() 
#36 0x3f345e9bec8a3d7a in ??() 
#37 0x3f43854a676ff7cb in ??() 
#38 0x3f4acbe712d1ba00 in ??() 
#39 0x3f191497deb0cd86 in ??() 
#40 0x3f48e220ec5df7ee in ??() 
#41 0x3f4326498a95447b in ??() 
#42 0x3f2e05ee4edaa6ff in ??() 
#43 0x3f285f8e79fe6b92 in ??() 
#44 0x3f58240bec575a1d in ??() 
#45 0x3f47c79be94754f7 in ??() 
#46 0x3f5cf356ce58b75a in ??() 
#47 0x3f28c2a87c82305d in ??() 
#48 0x3f35fca48157c9e4 in ??() 
#49 0x3f41c924b53cdbae in ??() 
#50 0x3f477c6c115fb520 in ??() 
#51 0x0000000000000000 in ??() 

여기 내 GDB 디버깅이 버그를 추적하는 세션이다. 3, Scientific Linux 5.6 (gfortran 4.3.4) 및 Microsoft Windows (gfortran 4.5.0-1). Linux 컴파일러에서 인텔 컴파일러를 사용할 때이 오류를 재현 할 수는 없지만 Windows에서 ifort를 사용할 수는 없습니다. 왜냐하면 필자는 학술 라이센스를 갖고 있기 때문입니다. 그러나 일부 학생을 위해 Windows 버전이 있어야하므로 gfortran으로이 문제를 해결해야합니다. 컴파일러 플래그 -funroll-all-loops -fno-f2c -O3 버전 및 플래그 -fno-f2c -O0 -g3 (디버그 버전 용)을 사용하고 있습니다. 두 옵션 모두 이러한 문제를 일으 킵니다.

또한이 버그는 큰 배열을 사용하는 경우에만 재현 할 수 있습니다. 최대 크기 (500, Ns) 배열과 작업 배열 크기 (Ns, Ns, 500)로 작업하고 있습니다. 시뮬레이션 충돌 사용하지 않을의 Ns (53) = 그것은 Ns를 = 153 충돌 않지만, Ns를이 200

의 선언 된 크기를 가질 때 마지막으로 나는 충돌 코드를 보여 드리겠습니다 : solver.f, 서브 루틴 trifactorize :

 lSing = .FALSE. 

     DO k = 1, Npoint 
c---- Compute (jacB(k)-jacA(k)*jacC(k-1)). ----------------------------- 
     SELECT CASE (k) 
      CASE (1) 
      CASE DEFAULT 
       CALL DGEMM('N', 'N', Ns, Ns, Ns, -1.0D0, jacA(:,:,k), 
    >      NsMax, jacC(:,:,k-1), NsMax, 1.0d0, 
    >      jacB(:,:,k), NsMax) 
     END SELECT 
c---- Factor with Gaussian elimination and estimate condition number.--- 
     norm = DLANGE('1', Ns, Ns, jacB(:,:,k), NsMax, Work) 
     CALL DGETRF(Ns, Ns, jacB(:,:,k), NsMax, ip(:,k), INFO) 
     CALL DGECON('1', Ns, jacB(:,:,k), NsMax, norm, Condit(k), 
    >    Work, IWork, INFO) 
c   WRITE(*,*)k,condit(k) 
     IF ((1.0d0+condit(k)).EQ.1.0d0 .AND. iLogging.EQ.iDebug) THEN 
      Write(line,10) 'Singular Jacobian Matrix' 
      CALL ScreenWrite(line, iNormal) 

      Write(line,11) 'Gridnumber: ', k 
      CALL ScreenWrite(line, iNormal) 

      lSing = .TRUE. 
      RETURN 
     ENDIF 

c---- Compute jacC/jacB'-matrix ---------------------------------------- 
     CALL DGETRS('N', Ns, Ns, jacB(:,:,k), NsMax, ip(:,k), 
    >    jacC(:,:,k), NsMax, INFO) 
     ENDDO 

10 FORMAT(9X,3('-'),1X,9('-'),1X,9('-'),1X,A) 
11 FORMAT(9X,3('-'),1X,9('-'),1X,9('-'),1X,A,i4) 

     CALL LogWrite('==> Decompose : Finished', iDebug) 

RETURN 

dlatrs.f :

* 
*   A is lower triangular. 
* 
      DO 20 J = 1, N - 1 
       CNORM(J) = DASUM(N-J, A(J+1, J), 1) 
    20  CONTINUE 
      CNORM(N) = ZERO 

내가 잘못 컴파일러 플래그를 사용하고 있다면이 궁금했는데, 아니면 드문 gfortran 버그를 우연히 발견 한 경우. 누군가는 이것을 해결하는 방법을 알고 있기를 바랍니다.

+4

한계 밖의 첨자를 포함하여 전체 런타임 오류 검사 옵션으로 컴파일 했습니까? gfortran을 사용하여 다음을 시도해보십시오. -fcheck = all –

+0

이 작업을 수행하여 제거해야하는 쓸모없는 코드를 발견했지만 코드에서 잘못된 점을 표시하지 않습니다. 그러나 나는 그 해결책을 실제로 발견했다고 생각한다. 나는 버그 리포트를 제출할 수 있도록 소스에서 최신 안정 버전의 gcc (4.7.0)를 빌드하지만,이 버전으로 컴파일하면 문제가 완전히 해결됩니다. – nspeelman

답변

0

내 우분투 컴퓨터에 gcc 4.7.0을 설치했고 내 Windows에 슬레이브를 설치했는데이 문제는 Windows와 Ubuntu에서 완전히 사라졌습니다. 그래서이 버그는 gcc 최신 버전으로 수정되었습니다.

+0

나는 당신이 clang + llvm으로 이사 할 것을 제안한다. – Aslan986

+0

내가 clang + llvm으로 옮겨야하는 이유를 말해 줄 수 있니? llvm의 Fortran은 여전히 ​​gcc가 있어야하며이 소프트웨어를 C/C++로 다시 작성하지는 않을 것입니다. 배경 : 우리는 CFD 화염 계산을위한 과학 소프트웨어의 큰 부분에 대해 이야기하고 있습니다. 내 발언자는 박사 과정 동안 내 무릎에 떨어졌습니다. 연구. 그래서 화염 거동은 CFD 코드 자체가 아니라 연구 주제입니다. – nspeelman

관련 문제