我可以将手表添加到 COMMON 块吗?
Can I add a watch to a COMMON block?
我有一组非常大、非常旧、非常复杂、非常没有文档记录的 Fortran 代码,我正在尝试对其进行故障排除。它在 运行 时给了我 divide-by-zero 问题,因为部分大致如下:
subroutine badsub(ainput)
implicit double precision (a-h,o-z)
include 'commonincludes2.h'
x=dsqrt((r(6)-r(8))**2+(z(6)-z(8))**2)
y=ainput
w=y+x
v=2./dlog(dsqrt(w/y))
此代码在最后一行命中除以零,因为 y
等于 w
因为 x
为零,因此 dlog(dsqrt(1)
为零。
包含文件看起来像这样:
common /cblk/ r(12),z(12),otherstuff
实际上有 3 个 include headers with /cblk/
我从 运行ning grep -in "/cblk/" *.h *.f *.F
中找到的声明:“commonincludes.h”,“commonincludes2.h”和“commonincludes3.h”。作为额外的奖励,对应于 r
和 z
的内存部分在“commonincludes.h”中被命名为 x
和 y
,即“commonincludes'h”看起来像:
common /cblk/ x(12),y(12),otherstuff
我的问题是,我不知道设置 r
和 z
的位置。我已经使用 grep
找到每个包含 headers 的地方,但我没有看到任何写入变量的地方。
如果我在发生错误的 gdb 中检查 r
和 z
中的实际值,这些值看起来很合理——它们是 non-zero、not-garbage-looking 向量的实数,只是 r(6)
等于 r(8)
和 z(6)
等于 z(8)
导致问题。
我需要找到写入 z
和 r
的位置,但我在 gdb 文档中找不到任何关于将观察点附加到 COMMON
块的说明。我怎样才能找到这些文件的写入位置?
我想我已经想出了如何做我想做的事情。因为 COMMON
变量是静态分配的,所以它们的地址不应该从 运行 运行 改变。因此,当我的程序由于我的 divide-by-zero 错误而停止时,我能够找到(在本例中)r(8)
的内存地址,它是全局范围的,不应在后续 运行s。然后,我可以 re-run 在该地址上带有观察点的代码,当代码中任何位置的值发生变化时,它都会进行标记。
在我的例子中,gdb 会话看起来像这样,进程名称和目录被归档以保护罪犯:
Reading symbols from myprogram...
(gdb) r
Starting program: ************
Program received signal SIGFPE, Arithmetic exception.
0x00000000004df96d in badsub (ainput=1875.0000521766287) at badsub.f:109
109 v=2./dlog(dsqrt(w/y))
(gdb) p &r(8)
= (PTR TO -> ( real(kind=8) )) 0xcbf7618 <cblk_+56>
(gdb) watch *(double precision *) 0x0cbf7618
Hardware watchpoint 1: *(double precision *) 0x0cbf7618
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: *************
Hardware watchpoint 1: *(double precision *) 0x0cbf7618
Old value = 0
New value = 6.123233995736766e-17
0x00007ffff6f2be2d in __memmove_avx_unaligned_erms () from /lib64/libc.so.6
我已经从 运行 回溯中确认这确实是我的公共块变量被设置的地方(大概是第一个地方)。
我有一组非常大、非常旧、非常复杂、非常没有文档记录的 Fortran 代码,我正在尝试对其进行故障排除。它在 运行 时给了我 divide-by-zero 问题,因为部分大致如下:
subroutine badsub(ainput)
implicit double precision (a-h,o-z)
include 'commonincludes2.h'
x=dsqrt((r(6)-r(8))**2+(z(6)-z(8))**2)
y=ainput
w=y+x
v=2./dlog(dsqrt(w/y))
此代码在最后一行命中除以零,因为 y
等于 w
因为 x
为零,因此 dlog(dsqrt(1)
为零。
包含文件看起来像这样:
common /cblk/ r(12),z(12),otherstuff
实际上有 3 个 include headers with /cblk/
我从 运行ning grep -in "/cblk/" *.h *.f *.F
中找到的声明:“commonincludes.h”,“commonincludes2.h”和“commonincludes3.h”。作为额外的奖励,对应于 r
和 z
的内存部分在“commonincludes.h”中被命名为 x
和 y
,即“commonincludes'h”看起来像:
common /cblk/ x(12),y(12),otherstuff
我的问题是,我不知道设置 r
和 z
的位置。我已经使用 grep
找到每个包含 headers 的地方,但我没有看到任何写入变量的地方。
如果我在发生错误的 gdb 中检查 r
和 z
中的实际值,这些值看起来很合理——它们是 non-zero、not-garbage-looking 向量的实数,只是 r(6)
等于 r(8)
和 z(6)
等于 z(8)
导致问题。
我需要找到写入 z
和 r
的位置,但我在 gdb 文档中找不到任何关于将观察点附加到 COMMON
块的说明。我怎样才能找到这些文件的写入位置?
我想我已经想出了如何做我想做的事情。因为 COMMON
变量是静态分配的,所以它们的地址不应该从 运行 运行 改变。因此,当我的程序由于我的 divide-by-zero 错误而停止时,我能够找到(在本例中)r(8)
的内存地址,它是全局范围的,不应在后续 运行s。然后,我可以 re-run 在该地址上带有观察点的代码,当代码中任何位置的值发生变化时,它都会进行标记。
在我的例子中,gdb 会话看起来像这样,进程名称和目录被归档以保护罪犯:
Reading symbols from myprogram...
(gdb) r
Starting program: ************
Program received signal SIGFPE, Arithmetic exception.
0x00000000004df96d in badsub (ainput=1875.0000521766287) at badsub.f:109
109 v=2./dlog(dsqrt(w/y))
(gdb) p &r(8)
= (PTR TO -> ( real(kind=8) )) 0xcbf7618 <cblk_+56>
(gdb) watch *(double precision *) 0x0cbf7618
Hardware watchpoint 1: *(double precision *) 0x0cbf7618
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: *************
Hardware watchpoint 1: *(double precision *) 0x0cbf7618
Old value = 0
New value = 6.123233995736766e-17
0x00007ffff6f2be2d in __memmove_avx_unaligned_erms () from /lib64/libc.so.6
我已经从 运行 回溯中确认这确实是我的公共块变量被设置的地方(大概是第一个地方)。