FORTRAN(自作splitのデバッグその5)

FORTRANでデバッグ続きです。

man gdbを見てみるとこのような一文がありました。

       GDB  では C, C++, Modula-2 などで書かれたプログラムのデバッグが行なえま
       す。 GNU Fortran コンパイラが完成すれば Fortran もサポートされます。

Fortranコンパイラが完成すればサポートされると書いてありますが、デバッグできててますね。FORTRANと書くとFORTRAN77以前のことで、Fortranと書くと90以降のことを言うらしいですが、90や95のプログラムでもGDB動かせるようです。

ちなみに使用しているGDBのバージョンはこれです。今は8があるのでちょっと古めです。

takk@deb9:~$ gdb --version
GNU gdb (Debian 7.12-6) 7.12.0.20161007-git

FORTRANプログラムの文字列変数をGDBで表示するとき、文字列が格納されていない領域が全部スペースなのでとても見にくいです。これをなんとか解消してデバッグしやすくならないでしょうか。

Breakpoint 1, b_opt (b_opt_string=..., _b_opt_string=98) at split4.f:15
15              CALL SPLIT(B_OPT_STRING,',', SSTRING1,SSIZE1)
(gdb) p B_OPT_STRING
$1 = '1,2,3,4,5', ' ' <repeats 89 times>, '\000\000'
(gdb) 

思いつくのは、先頭の空白の位置に0(NULL)を入れることぐらいです。
GDBから見ると普通の文字列が格納されているように見えます、きっと。
FORTRANのプログラムを、INDEXで空白を探し、代わりに0を格納するように改造してみます。

文字列に0を代入するのもエスケープシーケンスというものがあるかどうかも現状は分からないので、これまでで覚えたものを使ってやってみます。

takk@deb9:~$ cat -n split5.f
     1        PROGRAM MAIN
     2          CHARACTER*100 ARGS
     3          INTEGER*1 A(100),SP_LOC
     4          EQUIVALENCE (A,ARGS)
     5          CALL GETARG(1,ARGS)
     6          SP_LOC=INDEX(ARGS,' ')
     7          A(SP_LOC)=0
     8          IF(ARGS(1:2).EQ.'-b') THEN
     9            CALL B_OPT(ARGS(3:))
    10          END IF
    11          STOP
    12        END

3行目で文字列の途中にNULLを入れるための、配列変数Aを用意してます。
この配列変数AをEQUIVALENCEで文字列ARGSと結合させ、INDEXで見つけた空白の位置に、A(位置)=0とすることで、文字列ARGSに(GDBから見て)終端コードである空白を埋め込んでいます。

では-gオプションをつけて、ビルド後、GDBを起動してみましょう。

takk@deb9:~$ gfortran -g split5.f
takk@deb9:~$ gdb a.out

引数に”-b1,2,3,4,5″を設定し、mainでブレイクさせます。

(gdb) set args -b1,2,3,4,5
(gdb) b main
Breakpoint 1 at 0xdb4: file split5.f, line 12.
(gdb) run
Starting program: /home/takk/a.out -b1,2,3,4,5

Breakpoint 1, main (argc=2, argv=0x7fffffffe7e2) at split5.f:12
12            END
(gdb)

NULL埋め込み後、printfで文字列を確認します。

(gdb) step
MAIN__ () at split5.f:5
5               CALL GETARG(1,ARGS)
(gdb) next
6               SP_LOC=INDEX(ARGS,' ')
(gdb) n
7               A(SP_LOC)=0
(gdb) n
8               IF(ARGS(1:2).EQ.'-b') THEN
(gdb) printf "%s\n",&args
-b1,2,3,4,5
(gdb)

NULLを埋め込む前だと、いらない空白がたくさん出てしまっていましたが、必要な分だけ表示されました。

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA