如何调试 Fortran 代码中的意外跳转
How do I debug an unexpected jump in a Fortran code
我正在 ODE 求解器套件中实现事件检测。以下是我目前正在调试并注意到 st运行ge 行为的实现中的一段代码。一旦根查找例程 returns 成功找到根,第一个 if 块将被执行(ROOTFINDING_ERR == 0)——第 1 到 14 行——这是预期的行为。但是,一旦该块执行完毕,执行就会意外跳转到对应于 (ROOTFINDING_ERR == 0) 的 ELSE 块的最后一条语句——第 20 行——以及语句 EVENT_OUT(j) = 。错误的。在第 21 行执行 ENDIF 之前执行。
1 IF (ROOTFINDING_ERR == 0) THEN
2 IF ((ABS(EVENT_TIMES(1, j) - T_STAR) > &
3 NEARBY_ROOTS_ABSTOL) &
4 .AND. (EVENT_ITER < EVENT_ITER_MAX)) THEN
5 EVENT_TIMES(1, j) = T_STAR
6 EVENT_TIMES(2, j) = DBLE(j)
7 EVENT_TEST(j) = .TRUE.
8 EVENT_OUT(j) = .TRUE.
9 ELSE
10 EVENT_TIMES(1, j) = T_STAR
11 EVENT_TIMES(2, j) = DBLE(j)
12 EVENT_TEST(j) = .FALSE.
13 EVENT_OUT(j) = .TRUE.
14 ENDIF
15 ELSE
16 EVENT_TIMES(1, j) = T_STAR
17 EVENT_TIMES(2, j) = DBLE(j)
18 ! Dont test this event further
19 EVENT_TEST(j) = .FALSE.
20 EVENT_OUT(j) = .FALSE.
21 ENDIF
我认为这与可执行文件上的一些内存 access/allocation 问题和 运行 DrMemory(类似 Valgrind 的工具)有关。 DrMemory 确实指定一些读取未初始化,我将进一步研究。
我想知道从这里到哪里去。我确实使用 gdb 逐步执行了代码,但在隔离 DrMemory 抱怨的 "uninitialized read" 时遇到了一些困难。我打开 -Wall, -Wextra, -fbounds-check
等来确定编译器是否能够捕获它。我也尝试用 x32dbg 反汇编 exe,但是调试符号没有被读取,因为 x32dbg 不支持 DWARF 符号。
从显示的代码中我看不出错误的原因。因此我推测错误是由我们看不到的东西引起的。
现在,下面的内容并没有解决这个难题,而是试图绕过它...
...显示的代码可以简化为
EVENT_TIMES(1, j) = T_STAR
EVENT_TIMES(2, j) = DBLE(j)
IF (ROOTFINDING_ERR == 0) THEN
EVENT_OUT(j) = .TRUE.
IF ((ABS(EVENT_TIMES(1, j) - T_STAR) > &
NEARBY_ROOTS_ABSTOL) &
.AND. (EVENT_ITER < EVENT_ITER_MAX)) THEN
EVENT_TEST(j) = .TRUE.
ELSE
EVENT_TEST(j) = .FALSE.
ENDIF
ELSE
! Dont test this event further
EVENT_TEST(j) = .FALSE.
EVENT_OUT(j) = .FALSE.
ENDIF
...甚至更进一步...
EVENT_TIMES(1, j) = T_STAR
EVENT_TIMES(2, j) = DBLE(j)
EVENT_OUT(j) = ROOTFINDING_ERR == 0
EVENT_TEST(j) = ((ROOTFINDING_ERR == 0) .AND. &
(ABS(EVENT_TIMES(1, j) - T_STAR) > &
NEARBY_ROOTS_ABSTOL) &
.AND. (EVENT_ITER < EVENT_ITER_MAX))
我正在 ODE 求解器套件中实现事件检测。以下是我目前正在调试并注意到 st运行ge 行为的实现中的一段代码。一旦根查找例程 returns 成功找到根,第一个 if 块将被执行(ROOTFINDING_ERR == 0)——第 1 到 14 行——这是预期的行为。但是,一旦该块执行完毕,执行就会意外跳转到对应于 (ROOTFINDING_ERR == 0) 的 ELSE 块的最后一条语句——第 20 行——以及语句 EVENT_OUT(j) = 。错误的。在第 21 行执行 ENDIF 之前执行。
1 IF (ROOTFINDING_ERR == 0) THEN
2 IF ((ABS(EVENT_TIMES(1, j) - T_STAR) > &
3 NEARBY_ROOTS_ABSTOL) &
4 .AND. (EVENT_ITER < EVENT_ITER_MAX)) THEN
5 EVENT_TIMES(1, j) = T_STAR
6 EVENT_TIMES(2, j) = DBLE(j)
7 EVENT_TEST(j) = .TRUE.
8 EVENT_OUT(j) = .TRUE.
9 ELSE
10 EVENT_TIMES(1, j) = T_STAR
11 EVENT_TIMES(2, j) = DBLE(j)
12 EVENT_TEST(j) = .FALSE.
13 EVENT_OUT(j) = .TRUE.
14 ENDIF
15 ELSE
16 EVENT_TIMES(1, j) = T_STAR
17 EVENT_TIMES(2, j) = DBLE(j)
18 ! Dont test this event further
19 EVENT_TEST(j) = .FALSE.
20 EVENT_OUT(j) = .FALSE.
21 ENDIF
我认为这与可执行文件上的一些内存 access/allocation 问题和 运行 DrMemory(类似 Valgrind 的工具)有关。 DrMemory 确实指定一些读取未初始化,我将进一步研究。
我想知道从这里到哪里去。我确实使用 gdb 逐步执行了代码,但在隔离 DrMemory 抱怨的 "uninitialized read" 时遇到了一些困难。我打开 -Wall, -Wextra, -fbounds-check
等来确定编译器是否能够捕获它。我也尝试用 x32dbg 反汇编 exe,但是调试符号没有被读取,因为 x32dbg 不支持 DWARF 符号。
从显示的代码中我看不出错误的原因。因此我推测错误是由我们看不到的东西引起的。
现在,下面的内容并没有解决这个难题,而是试图绕过它...
...显示的代码可以简化为
EVENT_TIMES(1, j) = T_STAR
EVENT_TIMES(2, j) = DBLE(j)
IF (ROOTFINDING_ERR == 0) THEN
EVENT_OUT(j) = .TRUE.
IF ((ABS(EVENT_TIMES(1, j) - T_STAR) > &
NEARBY_ROOTS_ABSTOL) &
.AND. (EVENT_ITER < EVENT_ITER_MAX)) THEN
EVENT_TEST(j) = .TRUE.
ELSE
EVENT_TEST(j) = .FALSE.
ENDIF
ELSE
! Dont test this event further
EVENT_TEST(j) = .FALSE.
EVENT_OUT(j) = .FALSE.
ENDIF
...甚至更进一步...
EVENT_TIMES(1, j) = T_STAR
EVENT_TIMES(2, j) = DBLE(j)
EVENT_OUT(j) = ROOTFINDING_ERR == 0
EVENT_TEST(j) = ((ROOTFINDING_ERR == 0) .AND. &
(ABS(EVENT_TIMES(1, j) - T_STAR) > &
NEARBY_ROOTS_ABSTOL) &
.AND. (EVENT_ITER < EVENT_ITER_MAX))