今回使用するtankにはセッションファイルが添付されていません。
前項の手順を参考の上、お手元の環境に応じて[Project Setup]から環境を設定し、[File]メニューの[Session Save As]で、\katana\Shinobi\sample\tank\tank.ssnを作成してください。
まず最初は、意図的にコンパイルエラーになるようなものを仕込んでみましょう。
ファイルの先頭に、このように不要な文字列を入れてみました。
これをmakeすると次のようになります。
このようにエラーになりました。
続いてこのエラーを取り除きましょう。 [Editor Configuration]ウィンドウで指定したエディタが自動的に起動します 注10。
注10 |
問題のエラーは、不要な文字列が入っていることが原因ですのでこれを削除します。
変更後セーブし、再度[Project Build]ウィンドウからmakeします 注11。
注11 |
エラーがないことを確認したら、続いてこの実行ファイルをロードします。 [File]メニューの[Load Program File]をクリックすると、次のようなダイアログが表示されます 注12。
注12 |
一度ファイル名を指定して読み込んでおけば、以降はmake終了ごとに次のようなダイアログボックスが表示されますので、[はい]をクリックするだけで実行ファイルが自動的に再読み込みされます。
うまくコンパイルが終了していれば、次のいずれかの手順でDev.Box上で実行できます。
注13 |
続いてBreakpointの設定を行ってみましょう。
tankでは、実際のメインコードはmain.c中のnjUserMain();ですので、その中にBreakpointを設定してみます。以下にその手順を示します。 [Window]メニューの[New Window]をクリックして新しいリージョン(ウィンドウ)を開きます。
このように、未定義のリージョン(No type)が開きます。
今はBreakpointを設定するためにソースリストを表示させたいので、[Region Combo]ツールバーの[Source]をクリックします。
このリージョンのタイトルバーが[Source]に変わり、この[No type]リージョンは[Source]リージョンに設定されました 注14。
注14 |
続いて、この[Source]リージョンで右クリックし、[Goto Source File]をクリックします。
すると次のようなウィンドウが開き、このプログラムで使用されているソースファイルの一覧がリストされます。
この中から開きたいソースファイルを選択します。
今開きたいソースはmain.cですから、この中からmain.cを選択します。
これで[Source]リージョンにmain.cが表示されました。
画面上にスプライトを表示している行(107行目)にBreakpointを設定してみます。スクロールダウンし、その行をクリックします。
この状態で、次のいずれかの方法で設定できます。
または次の方法でも可能です。この場合、指定したい行をクリックする必要はありません(右クリックした時に、その時のカーソルの位置に設定されます)。
すると、行頭にBreakpointが設定されたことを示すマークがつきます 注15。
注15 |
これでこの行にBreakpointが設定されました。
それでは[F9]キーを押して実行してみましょう。
行頭のマークがSTOPに変わり、また[Target]ウィンドウも
と表示され、プロセッサがここで停止したことが分かります 注16。
注16 |
続いて、特定の変数にアクセスされた時に停止するような設定(Watch access breakpoint)を行ってみましょう。
このようなダイアログが表示されました。
先ほど設定したBreakpointが有効なままですので、その情報が表示されています。
ここで[Add Watch]ボタンをクリックします。 [Code Setting]タブが[Watch Settings]タブに変わります。
それでは、変数countのアクセスに対して停止するようにしてみましょう。 [Local Expression]に「&count」と入れ、またこれはC/C++の表記方法ですので、下のオプションボックスで[C/C++]を選択します。そして[OK]をクリックします。
これで、以降は変数countにアクセスが入るごとに停止するようになります 注17。
注17 |
それでは[F9]キーを押して再実行してみましょう。
すぐに次のようなダイアログボックスが表示され、変数countがアクセスされたことが分かります。
[Source]リージョンを見ると、
ソース中に変数countが出てきている付近で停止しています。
このようにWatch access breakpointには注意しなければいけない点があります。
ここで[Disassemble]リージョンを開いてみます。
実際に変数countにアクセスが入ったのは、現在のPC値より3行前のようです。
このように、Watch access breakpointがトリガされる時PCはパイプライン中で、すでに数命令先を処理しています(よってズレが生じてしまいます)。
このことに気を付けてください。
このWatch access breakpointの解除は、上の[Configure breakpoint(s)]ダイアログで、下にリストされているBreakpointの一覧から解除したいものをクリックして選択し、[Remove]ボタンをクリックすることで行います。
これでWatch access breakpointが解除されました。
Breakpointには、ここで示した以外に、色々な条件を設定してのBreakpoint処理が可能です。詳細は『CodeScapeマニュアル』をご覧ください。
実行中の変数の値を見てみましょう。
[Watch]リージョンを開きます。
では、ここでのカウンターである変数count(int count)の値を見ることにしましょう。
右クリックして[Insert]をクリックします。カーソルが点滅しますので、countと入力します。
変数countの、現在の値が表示されました。
先ほどのBreakpointの設定を解除していない場合、[F9]キーを押すごとにBreakpointで停止しますので、この値が1ずつカウントアップしていくことを確認してください。
続いてこの変数の値を変更してみましょう。 [Watch]リージョンで変数countを左クリックで選択し、右クリックします。そして[Edit Watch Value]をクリックすると、次のようなウィンドウが表示されます。
この[Expression]に直接値を入力することで変数の内容を変更することができます 注18。
注18 |
新しい値を設定して[OK]ボタンをクリックするとこのウィンドウが閉じ、[Watch]リージョンに新しい値が入っているはずです。確認してください。
この状態で再実行を行うと、新しい値で表示が始まります。
再実行は、次のいずれかの操作で行います。
注19 |
ちなみに[Memory]リージョンから変数の値を見ることも可能です。
配列など、連続したアドレスの値を見るにはこちらが便利な場合もあるでしょう。 [Memory]リージョンを開きます。
開いた直後の状態では、現在のプログラムカウンター(PC)値を先頭とする表示(メモリダンプ)を行っています。 [Memory]リージョンで右クリックし、[Goto Address...]をクリックします。
ここで[Expression]に変数名を入れます。但し先頭にシンボル名であることを示す「&」を付けることを忘れないでください。 [OK]ボタンをクリックすると、変数countの、メモリ上のアドレス(変数countの内容が格納されているアドレス)を先頭とする表示に変わります。
この先頭アドレス(0x8C016E70)が、[Watch]リージョンで見た変数countのアドレスと同じであることを確認してください。
変数countの型はintつまり4バイト長ですから、このメモリダンプで先頭からの4バイト、ここでは“0A 00 00 00”がその値であることが分かります。
デバッグ上、プログラムがどのような流れで実行されてきているのか調べたい時があります。このような時には[Call Stack]リージョンが役に立ちます。 [Call Stack]リージョンを開きます。
最上段に現在のプログラムカウンタ(PC)、そしてその下に現在のプログラムスタックの状態がリストされています(リストは下に行くほど古いものになります)。
ここにはアドレスが、関数名、またその関数名からのオフセット値で示されています(今、先ほどのBreakpointが有効なままですので、その行で停止しています 注20)。
注20 |
確認のため、この状態から[Disassemble]リージョンを開いて見てみましょう 注21。
注21 |
開いた直後は、カーソル位置が現在のPCです。
確かに現在その位置(njUserMain()+0x02)にいることが分かります。
その1つ下のスタックも確認してみましょう。
Call Stackリージョンの、“main() + 0xa”の行をダブルクリックします。
このように表示が変わり、またこれに連動して[Disassemble]リージョンと[Source]リージョンのカーソル位置が、このnjUserMain();関数の呼び出しを行った個所に移ります。
ところで今現在、このように[Source]リージョンと[Disassemble]リージョンが同時に開いているはずですが、この2つは同期を取って、つまり片方の動きに合わせてもう片方を動かすことが可能です(具体的な方法については『CodeScapeマニュアル』を参照してください)。ソースレベルで取りきれないバグについては、この方法で調査することになります 注22。
注22 |
CoceScapeは幾つかのトレース実行機能を持っています。
これらの機能はデバッグツールバーから呼び出すことができます。
現在のカーソル位置まで実行し、停止します。
ここでは、先ほどBreakpointを設定した行の位置まで、この機能で実行することにしましょう。[Source]リージョンを開きます。
以前のBreakpointが残っている場合には、その行で[F5]キーを押してこれを解除します。
続いて、カーソルを実行したい行の位置に持って行きます 注23。
注23 |
この状態で、次のいずれかの方法で現在のカーソル位置まで実行します。
すると表示が次のように変わり、カーソル位置まで実行され、停止したことがわかります。
またこの時[Target]ウィンドウは
指定したアドレスまで実行し、停止します。
次のようなダイアログボックスが表示されます。
ここで今表示されている値は、現在のPC値です。[Expression]に関数名であるnjUserMainと入力し、[Evaluate]ボタンをクリックして関数名をアドレスに展開させます。
関数名が式として評価され、下に値(アドレス)が表示されました 注24。
注24 |
ここで[OK]ボタンをクリックすると、njUserMain();の先頭まで実行されます。
与えた式が満たされるまで実行します。
[Expression]に条件式を入れます。
この式が満たされるまで実行されます。
しかしながらこの機能はかなり実行時間がかかります 注25。つまり実時間動作が行えません。このことが原因で期待したトレースが行えない場合があることも頭に入れて使用してください。またWatch access breakpointと同様、停止した時には既にアセンブラレベルで数命令先に進んでいることにも気を付けてください。
注25 |
プログラムを1行単位で実行します。
ステップ実行には、以下の3種類の方法があります。
これらの機能を1つずつ見て行ってみましょう。
呼び出した関数や、サブルーチンの中もトレースします。
Step intoは以下のいずれかの操作で行い、これらを行うごとに1行ごと進みます。
たとえば上の状態で停止している場合、[F7]キーを1回押します。
1行分進みました(宣言文や空行は実行されません)。
この時点で現在のカーソル位置までは未だ実行されていないことに気を付けてください。
何度か[F7]キーを押し、進めてみます。
すると、あるところからソースが見えなくなってしまいました。
これはソースのない、ライブラリ内関数njDrawSprite2D();内部のトレースに入ったためです 注26。この場合、後に述べるStep Overを使用して、先ほどのソースまで進めることができます。またトレースの必要ない関数の場合、これも後に述べるStep Outを使用してスキップする(実行するが、トレース状況を表示しない)ことができます。
このStep intoを行った場合に限り、Unstepで1行づつプログラムを逆に戻ることができます。
注26 |
Unstepは以下のいずれかで行います。
Step intoでは関数コールやJSR、BSRがあった場合には呼び出した関数またはサブルーチンの中までトレースしましたが、Step overではそれを行いません。
まず既に説明したBreakpointの設定機能を使い、njDrawSprite2D();が呼ばれるところまで実行しましょう。
ここで[F8]キーを1回押します。
このように、Step intoと異なり関数njDrawSprite2D();の内部までのトレースは行いません。
ちなみに[Watch]リージョンで変数countの値を見ている場合、ここで変数countの値が変わることが分かります。
現在いる関数またはサブルーチンの終わりまで実行し、関数を抜けます。
意図しない動作がある場合トレースなどを行うことになりますが、トレースを行う時、特定の怪しそうなところを重点的に見ておきたいことがあります。
そのような時には[Source]リージョンにLock Viewを行います。Lock Viewを行うことで、PC値によらず特定のソースファイルの特定の個所を常に表示させておくことができます。
まず[Source]リージョンを開きます。
をクリックします。
[File]をクリックすると、ソースファイルの一覧が表示されます。
常に表示させておきたい(ロックしたい)ファイルを指定します。
ここではmain.cをクリックします。
[Expression]にファイル名が入りました。ファイル名の後の:に続けてソースファイルの行指定を行うことで、特定の個所にLockをかける(特定の行からの表示を行う)ことができます。
Lockされたリージョンは、スクロールバーの操作なども無効になります。
解除するには再度
をクリックし、[Lock View]ダイアログで[OK]ボタンをクリックします。
続いて変数の内容を調べる場合、調べたい変数名を1つ1つ打ち込んでも良いのですが、[Local watch]リージョンを開くことで、その関数のローカル変数一覧を見ることができます。
停止している時に、[Local watch]リージョンを開きます。
停止している個所の関数で使用されているローカル変数の一覧とその内容が表示されます。
ここではnjUserMain();のローカル変数が表示されています。
ローカル変数が構造体の場合、その構造体名の上で右クリックし[Open/Close]を選ぶことで、構造体のメンバ一覧とその内容を見ることができます 注27。
注27 |
[←] | [INDEX] | [→] |
(C)SEGA ENTERPRISES, LTD., 1998