Могу ли я добавить часы в ОБЩИЙ блок?

У меня есть очень большой, очень старый, очень запутанный, очень недокументированный набор кода Fortran, который я пытаюсь устранить. Это дает мне проблемы с делением на ноль во время выполнения из-за раздела, который выглядит примерно так:

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 заголовка включения с объявлением /cblk/, которые я нашел при запуске grep -in "/cblk/" *.h *.f *.F: «commonincludes.h», «commonincludes2.h» и «commonincludes3.h». В качестве дополнительного бонуса раздел памяти, соответствующий r и z, назван x и y в "commonincludes.h", т.е. "commonincludes'h" выглядит так:

common /cblk/ x(12),y(12),otherstuff

Моя проблема в том, что я НЕ ПОНИМАЮ, где установлены r и z. Я использовал grep, чтобы найти все места, где есть каждый из заголовков, и я не вижу места, куда записываются переменные.

Если я проверю фактические значения в r и z в gdb, где возникает ошибка, значения выглядят разумными - они ненулевые, не похожие на мусор векторы действительных чисел, просто r(6) равно r(8) и z(6) равно z(8), что вызывает проблему.

Мне нужно найти, где пишутся z и r, но я не могу найти инструкции в документации gdb для присоединения точки наблюдения к блоку COMMON. Как я могу найти, где они написаны?

Вместо того, чтобы следить за общим блоком, можете ли вы следить за объектами в общем блоке/локальными переменными, которые вас интересуют?

francescalus 05.05.2022 19:13

Если я попытаюсь, это не сработает, я думаю, из-за того, как работают обычные блоки. Насколько я понимаю, они буквально представляют собой блок памяти — я могу вызвать common /cblk/ x(12),y(12) в одной подпрограмме и получить common /cblk/ z(24) в другом месте, и Фортран не дрогнет на это, пока определения блоков имеют одинаковый размер. Как и в моем примере, одна и та же переменная называется r и x в зависимости от того, какой заголовок используется — как мне указать gdb следить за этим?

Frank 05.05.2022 22:00

Внутри любой области у вас может быть не более одной версии этого общего определения блока, поэтому следите за соответствующей локальной переменной в этой области. То есть, если вы просматриваете r в badsub, вы будете отслеживать изменения в r через ассоциацию хранения, независимо от имени другого объекта, связанного с этим r.

francescalus 05.05.2022 22:11

@francescalus Ключевая часть моей проблемы заключается в том, что я не знаю, в какой области на самом деле находится код, который мне нужно отслеживать. Если не считать установки около 30 точек останова для каждой подпрограммы, которая может быть важна, и установки часов всякий раз, когда они вводятся (что не очень практично с этим спагетти-кодом), я не знаю, как это сделать. Можете ли вы указать область, когда вы устанавливаете часы?

Frank 06.05.2022 00:58
Библиотека для работы с мороженым
Библиотека для работы с мороженым
Лично я попрощался с операторами print() в python. Без шуток.
3
4
80
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, что понял, как делать то, что я пытаюсь сделать. Поскольку переменные COMMON распределяются статически, их адреса не должны меняться от запуска к запуску. Поэтому, когда моя программа останавливается из-за моей ошибки деления на ноль, я могу найти адрес памяти (в этом примере) r(8), который является глобальным по объему и не должен меняться при последующих запусках. Затем я могу повторно запустить код с точкой наблюдения по этому адресу, и он будет сигнализировать об изменении значения в любом месте кода.

В моем примере сессия 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)
$1 = (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

Я подтвердил после запуска обратной трассировки, что это действительно место (предположительно первое место), где устанавливается моя переменная общего блока.

Другие вопросы по теме