시뮬레이션 소프트웨어를 충돌시키는 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 버그를 우연히 발견 한 경우. 누군가는 이것을 해결하는 방법을 알고 있기를 바랍니다.
한계 밖의 첨자를 포함하여 전체 런타임 오류 검사 옵션으로 컴파일 했습니까? gfortran을 사용하여 다음을 시도해보십시오. -fcheck = all –
이 작업을 수행하여 제거해야하는 쓸모없는 코드를 발견했지만 코드에서 잘못된 점을 표시하지 않습니다. 그러나 나는 그 해결책을 실제로 발견했다고 생각한다. 나는 버그 리포트를 제출할 수 있도록 소스에서 최신 안정 버전의 gcc (4.7.0)를 빌드하지만,이 버전으로 컴파일하면 문제가 완전히 해결됩니다. – nspeelman