2-2 デバッグの実際


2-2-1 プロジェクトの設定

今回使用するtankにはセッションファイルが添付されていません。

前項の手順を参考の上、お手元の環境に応じて[Project Setup]から環境を設定し、[File]メニューの[Session Save As]で、\katana\Shinobi\sample\tank\tank.ssnを作成してください。

2-2-2 エラー発生からソースエディット

まず最初は、意図的にコンパイルエラーになるようなものを仕込んでみましょう。

ct020000.gif

ファイルの先頭に、このように不要な文字列を入れてみました。

これをmakeすると次のようになります。

ct020046.gif

このようにエラーになりました。

続いてこのエラーを取り除きましょう。 [Editor Configuration]ウィンドウで指定したエディタが自動的に起動します 注10

注10
この時、指定したエディタがタグジャンプ機能を持っていて、かつ[Editor Configuration]ウィンドウのEditor Argumentでその機能が指定されている場合、エラー行にカーソルが移動します。

問題のエラーは、不要な文字列が入っていることが原因ですのでこれを削除します。

ct020002.gif

変更後セーブし、再度[Project Build]ウィンドウからmakeします 注11

注11
makeのショートカットキーは[Ctrl]+[M]です。

ct020047.gif

エラーがないことを確認したら、続いてこの実行ファイルをロードします。 [File]メニューの[Load Program File]をクリックすると、次のようなダイアログが表示されます 注12

注12
ショートカットキーは[Ctrl]+[Shift]+[C]です。

ct010002.gif

一度ファイル名を指定して読み込んでおけば、以降はmake終了ごとに次のようなダイアログボックスが表示されますので、[はい]をクリックするだけで実行ファイルが自動的に再読み込みされます。

ct0202006.gif

うまくコンパイルが終了していれば、次のいずれかの手順でDev.Box上で実行できます。

注13
[F9]キーは、RunとStopのトグルになっています。

以上が、基本的な修正から再makeへの流れです。

2-2-3 Breakpointの設定

続いてBreakpointの設定を行ってみましょう。

tankでは、実際のメインコードはmain.c中のnjUserMain();ですので、その中にBreakpointを設定してみます。以下にその手順を示します。 [Window]メニューの[New Window]をクリックして新しいリージョン(ウィンドウ)を開きます。

ct0202007.gif

このように、未定義のリージョン(No type)が開きます。

今はBreakpointを設定するためにソースリストを表示させたいので、[Region Combo]ツールバーの[Source]をクリックします。

ct020005.gif

このリージョンのタイトルバーが[Source]に変わり、この[No type]リージョンは[Source]リージョンに設定されました 注14

注14
本書では以降この一連の手順を、単に「〜リージョンを開く」と呼びます。

続いて、この[Source]リージョンで右クリックし、[Goto Source File]をクリックします。

すると次のようなウィンドウが開き、このプログラムで使用されているソースファイルの一覧がリストされます。

ct020006.gif

この中から開きたいソースファイルを選択します。

今開きたいソースはmain.cですから、この中からmain.cを選択します。

ct020007.gif

これで[Source]リージョンにmain.cが表示されました。

ではこの中にBreakpointを設定してみましょう。

特定の行にBreakpointを設定する

特定変数へのアクセスで停止

2-2-4 値の内容チェック

実行中の変数の値を見てみましょう。

[Watch]リージョンを開きます。

ct020019.gif

では、ここでのカウンターである変数count(int count)の値を見ることにしましょう。

右クリックして[Insert]をクリックします。カーソルが点滅しますので、countと入力します。

ct020020.gif

変数countの、現在の値が表示されました。

先ほどのBreakpointの設定を解除していない場合、[F9]キーを押すごとにBreakpointで停止しますので、この値が1ずつカウントアップしていくことを確認してください。

続いてこの変数の値を変更してみましょう。 [Watch]リージョンで変数countを左クリックで選択し、右クリックします。そして[Edit Watch Value]をクリックすると、次のようなウィンドウが表示されます。

ct020021.gif

この[Expression]に直接値を入力することで変数の内容を変更することができます 注18

注18
ここには式を入れることも可能です。式を入れて[Evaluate]をクリックしてください。式が展開され、変数にその値が代入されます。

新しい値を設定して[OK]ボタンをクリックするとこのウィンドウが閉じ、[Watch]リージョンに新しい値が入っているはずです。確認してください。

ct0202024.gif

この状態で再実行を行うと、新しい値で表示が始まります。

再実行は、次のいずれかの操作で行います。

注19
[F9]キーは、RunとStopのトグルになっています。

ちなみに[Memory]リージョンから変数の値を見ることも可能です。

配列など、連続したアドレスの値を見るにはこちらが便利な場合もあるでしょう。 [Memory]リージョンを開きます。

ct020023.gif

開いた直後の状態では、現在のプログラムカウンター(PC)値を先頭とする表示(メモリダンプ)を行っています。 [Memory]リージョンで右クリックし、[Goto Address...]をクリックします。

ct0202026.gif

ここで[Expression]に変数名を入れます。但し先頭にシンボル名であることを示す「&」を付けることを忘れないでください。 [OK]ボタンをクリックすると、変数countの、メモリ上のアドレス(変数countの内容が格納されているアドレス)を先頭とする表示に変わります。

ct020025.gif

この先頭アドレス(0x8C016E70)が、[Watch]リージョンで見た変数countのアドレスと同じであることを確認してください。

変数countの型はintつまり4バイト長ですから、このメモリダンプで先頭からの4バイト、ここでは“0A 00 00 00”がその値であることが分かります。

2-2-5 プログラムの流れを調べる

デバッグ上、プログラムがどのような流れで実行されてきているのか調べたい時があります。このような時には[Call Stack]リージョンが役に立ちます。 [Call Stack]リージョンを開きます。

ct020026.gif

最上段に現在のプログラムカウンタ(PC)、そしてその下に現在のプログラムスタックの状態がリストされています(リストは下に行くほど古いものになります)。

ここにはアドレスが、関数名、またその関数名からのオフセット値で示されています(今、先ほどのBreakpointが有効なままですので、その行で停止しています 注20)。

注20
Dev.Boxの実行中、[Call Stack]リージョンにはRUNNING...とだけ表示されます。

確認のため、この状態から[Disassemble]リージョンを開いて見てみましょう 注21

注21
また[Disassemble]リージョンの表示から、SH4 CPUは2バイトを1命令の単位としていることも分かります。

ct020027.gif

開いた直後は、カーソル位置が現在のPCです。

確かに現在その位置(njUserMain()+0x02)にいることが分かります。

その1つ下のスタックも確認してみましょう。

Call Stackリージョンの、“main() + 0xa”の行をダブルクリックします。

ct020028.gif

このように表示が変わり、またこれに連動して[Disassemble]リージョンと[Source]リージョンのカーソル位置が、このnjUserMain();関数の呼び出しを行った個所に移ります。

ct020029.gif

ct020030.gif

ところで今現在、このように[Source]リージョンと[Disassemble]リージョンが同時に開いているはずですが、この2つは同期を取って、つまり片方の動きに合わせてもう片方を動かすことが可能です(具体的な方法については『CodeScapeマニュアル』を参照してください)。ソースレベルで取りきれないバグについては、この方法で調査することになります 注22

注22
SH4 CPUについての知識と、コンパイラの動作の理解が必要になります。

2-2-6 トレース

CoceScapeは幾つかのトレース実行機能を持っています。

これらの機能はデバッグツールバーから呼び出すことができます。

ct0202033.gif

カーソル位置まで実行(Run to cursor)

指定アドレスまで実行(Run to Address)

条件が満たされるまで実行(Run until)...

ステップ実行

関数の中もトレース(Step into)

関数の中はトレースしない(Step over)

この関数から抜け出る(Step Out)

2-2-7 ソースリスト中の、特定の範囲をチェックする

意図しない動作がある場合トレースなどを行うことになりますが、トレースを行う時、特定の怪しそうなところを重点的に見ておきたいことがあります。

そのような時には[Source]リージョンにLock Viewを行います。Lock Viewを行うことで、PC値によらず特定のソースファイルの特定の個所を常に表示させておくことができます。

まず[Source]リージョンを開きます。

ct020048.gif

ct0202047.gif をクリックします。

ct0202048.gif

[File]をクリックすると、ソースファイルの一覧が表示されます。

ct020051.gif

常に表示させておきたい(ロックしたい)ファイルを指定します。

ここではmain.cをクリックします。

ct020052.gif

[Expression]にファイル名が入りました。ファイル名の後の:に続けてソースファイルの行指定を行うことで、特定の個所にLockをかける(特定の行からの表示を行う)ことができます。

Lockされたリージョンは、スクロールバーの操作なども無効になります。

解除するには再度 ct0202051.gif をクリックし、[Lock View]ダイアログで[OK]ボタンをクリックします。

変数の内容を見る