FORTRAN(自作splitのデバッグ)

ではFORTRANの自作split関数をGDBデバッグしていきます。

splitする文字列はこれです。

 STRING='1-3,5,7-12,13,14'

まず、カンマでsplitして、次にハイフンでsplitします。
結果は、このようになりました。

takk@deb9:~$ ./a.out
 1-3,5,7-12,13,14                                                               
SSIZE1=  5
[1-3       ]
  SSIZE2=  5
[5         ]
  SSIZE2=  4
[7-12      ]
  SSIZE2=  4
[13        ]
  SSIZE2=  3
[14        ]
  SSIZE2=  4
takk@deb9:~$

カンマは4箇所ありますのでsplitすると、split後の文字列の個数SSIZE1が5となります。
その後、1-3に含まれるハイフンでsplitすると、SSIZE2は2となるはずなのですが、なぜか5と表示されています。これをデバッグします。
-gオプションをつけてビルド後、GDBを起動します。

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

~

(gdb)

listコマンドでソースの1行目~20行目を確認します。

(gdb) l 1,20
warning: Source file is more recent than executable.
1             PROGRAM MAIN
2               CHARACTER*100 STRING
3               CHARACTER*10 SSTRING1(10),SSTRING2(10)
4               INTEGER I,SSIZE1,SSIZE2
5
6               STRING='1-3,5,7-12,13,14'
7               WRITE(*,*) STRING
8
9               CALL SPLIT(STRING,',', SSTRING1,SSIZE1)
10              WRITE(*,1100) SSIZE1
11
12              DO 100 I=1,SSIZE1
13
14                WRITE(*,1300) SSTRING1(I)
15
16                CALL SPLIT(SSTRING1(I),'-', SSTRING2,SSIZE2)
17                WRITE(*,1200) SSIZE2
18
19        100   CONTINUE
20       1100   FORMAT('SSIZE1=',I3)
(gdb)

ハイフン指定するときのSPLITの呼び出しでブレイクしたいので、b 16してrun

(gdb) b 16
Breakpoint 1 at 0xf5a: file split2.f, line 16.
(gdb) r
Starting program: /home/takk/a.out
 1-3,5,7-12,13,14                                                               
SIZE1=  5
[1-3       ]

Breakpoint 1, MAIN__ () at split2.f:16
16                CALL SPLIT(SSTRING1(I),'-', SSTRING2,SSIZE2)
(gdb)

SPLIT関数へ渡す引数を確認します。SSTRING1配列は初回はI=1ですので、SSTRING(1)について値を確認します。

(gdb) p sstring1(1)
$1 = '1-3       '
(gdb)

カンマで分割された文字列が格納されるので1-3となっています。ただ、1-3の後に配列サイズ分空白が入ってるのが以前から気になっていましたが、置いておきます。

次にsplit関数内を見ていくので、ステップインします。

(gdb) s
split (src=..., sep=..., dest=..., split_size=32767, _src=10, _sep=1, _dest=10)
    at split2.f:34
34              IND = 0
(gdb)

先ほど見たばかりですが、引数についてもう一度確認してみます。
引数として渡された文字列はsrc変数となっていますので、p srcします。

(gdb) p src
$2 = '1-3       5         7-12      13        14        \377\377\000\000\000\000\210v\335\367\377\177\000\000 IUUUU\000\000\300\345\377\377\377\177', '\000' <repeats 18 times>, '\340\344\377\377'
(gdb)

おかしいです。1-3だけのはずが、元の文字列すべて表示されてしまいます。
もしかして後に続く文字列は全部表示されているのでしょうか。

この場所でブレイクポイントを設定します。

(gdb) b
Breakpoint 2 at 0x555555554a71: file split2.f, line 34.
(gdb)

ブレイクポイントまで実行。

(gdb) c
Continuing.
  SIZE2=  3
[5         ]

Breakpoint 1, MAIN__ () at split2.f:16
16                CALL SPLIT(SSTRING1(I),'-', SSTRING2,SSIZE2)
(gdb)

同じようにsstring1(2)を確認。

(gdb) p sstring1(2)
$3 = '5         '
(gdb)

想定通りです。ではSPLIT関数内部に移動して再度引数を確認します。

(gdb) s

Breakpoint 2, split (src=..., sep=..., dest=..., split_size=3, _src=10,
    _sep=1, _dest=10) at split2.f:34
34              IND = 0
(gdb) p src
$4 = '5         7-12      13        14        \377\377\000\000\000\000\210v\335\367\377\177\000\000 IUUUU\000\000\300\345\377\377\377\177', '\000' <repeats 18 times>, '\340\344\377\377\003\000\000\000\005\000\000\000\002\000'
(gdb)

予想通り、次は1-3の文字列は表示されず、5と、それ以降の文字列が表示されました。
続く

Leave a Reply

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

CAPTCHA