プログラムの中にある間違いをバグと言います。元々バグは「虫」という意味です。プログラムの間違いを悪い虫にたとえているわけです。エラーという言葉も同様の意味で使われます。
バグを修正することをデバッグと言います。バグが虫なので、「バグを取る」という表現がよく使われます。プログラミングを学び始めて「プログラム作るのって楽しいなあ」と思っていた人がある日突然頭を抱えてしまう。バグが取れないからです。簡単に修正できるものであればいいのですが、隅々まで読み直しても原因がさっぱり分からない、マニュアルを読んでも分からない、というものはやっかいです。
ここでは、デバッグのやり方についてヒント程度ではありますが書いておこうと思います。
プログラムを実行してエラーが起こると、エラーメッセージ、問題があると思われる行番号、そしてHSP Debug windowというウィンドウが表示されます。
このウィンドウには、プログラム中で使われている変数名と代入されている値が表示されます。変数名をクリックして、「値=〜」とある箇所が入っている値です。このままでは配列変数は表示されません。「配列変数を表示」のチェックボックスをチェックすると表示されます。ただし、表示されるのは1次元配列までです。2次元以上は表示されません。
エラーメッセージの意味はHSPのヘルプに書いてあります。ここでは、補足的な事柄を書きます。(補足したい事があるもののみ。)
- 文法が間違っています
字が間違っている時によく起こります。存在しない命令を書くとこのエラーが出ます。つづりが間違ってないかよく確認して下さい。変数への代入文で、"="以降を書き忘れてしまった場合もこのエラーが出ます。例えば"height=0"と書こうとして"height"だけ書いてしまった場合です。heightという命令はないのでこのエラーとなります。
- パラメータの型が違います
パラメータというのは引数のことです。
a=0
repeat 3
a=a+2
dialog a
loop
dialog命令の第1引数は文字列型ですので上のエラーとなります。この場合、
a=0
repeat 3
a=a+2
str a
dialog a
int a
loop
または、
a=0
repeat 3
a=a+2
dialog ""+a
loop
と書きます。
- 配列の要素が無効です
dim文で宣言した要素数を超えた配列変数を使おうとした場合に起こります。例えば敵の種類を最大10種類と宣言していて、11個目を作る頃にはすっかりその事を忘れていて、このエラーが出て一瞬頭が混乱したりします。
ちなみにdim文は省略することができます。省略した場合要素数は16となります。個人的にはプログラムが分かりにくくなるだけなので、dim文を省略することはお勧めしません。
- 〜のネストが深すぎます
ネストというのは前に書いた「入れ子」のことです。例えばrepeat文は2重、3重にネストすることができますが、数が多すぎるとこのエラーが出ます(15重まで可)。普通にプログラミングしていればそんなにネストが深くなることはありません。が、repeat文からgotoで抜けるとこのエラーとなります。
*aaa
repeat
goto *aaa
loop
これは、
repeat
repeat
repeat
・
・
・
loop
loop
loop
と書いているのと同じです。
- サブルーチン外のreturnは無効です
m=2
n=5
gosub *njyou
mes answer
; mのn乗を計算するサブルーチン
*njyou
answer=1
repeat n
answer=answer*m
loop
return
プログラムは上から下へと順々に命令が実行されます。上のプログラムでは、"mes answer"が実行された後、その下の部分まで実行されてしまいます。gosubで呼んでないのにreturnが実行されるので、このエラーが出ます。"mes answer"の下に"stop"が必要です。
- バッファオーバーフローが発生しました
a=curdir
mes a
stop
curdirは現在のディレクトリパスを表すシステム変数です。つまりこのプログラムが入っているフォルダのディレクトリパスです。パスが長いとこのエラーとなります。ダウンロードしたゲームやツールをユーザがどこに置くかなど分かりません。作った人の環境ではちゃんと動いているのに、他の人の環境ではうまく動かないかもしれません。
ここでいうバッファとは、文字列型変数aの中身を入れておくための、メモリ上の場所です。何も指定しなかった場合、この大きさは64バイトとなります。オーバーフローとは、入れようとする文字列がその長さを超えてしまうことです。
この大きさは以下の命令で変えることができます。
sdim a,256
sdimは文字列型の配列変数を宣言する命令だと書きましたが、普通の文字列型変数の大きさを変えたい場合は上のように書きます。この場合256バイトにします。
上のようにエラーメッセージが出るものはまだいいのです。指定された行を見て、おかしな書き方をしていないか確認すればいいです。問題なのは、エラーにはならないが、自分が想定したのとは全然違う動作をしてしまうというものです。
また、エラーメッセージは表示されるが、修正すべき箇所が指定行とは別の場所にある場合もあります。その場合も、エラーメッセージをヒントに修正箇所を自分で探す必要があります。
(1)現象と条件をはっきりさせる
どんな時に、どうなるのか。たいていの場合、何度かプログラムを走らせればはっきりすると思います。
速すぎてよく分からない場合は、メインループ中のawaitの値を大きくして、スピードを落として確認します。おかしくなる瞬間が見たい場合は、そこの処理中にstop命令を入れます。
(2)プログラムを読み直す
現象と条件を確認したら、原因があると思われる箇所を読み直します。たいていは今追加した処理に原因があります。テストプレイをしているうちに、昨日書いた処理のバグを見つけることもあります。その場合は昨日書いた処理を読み直します。
今日追加した処理のために昨日書いた処理がうまく動かなくなることもあります。その場合は両方読み直します。
変数のつづりは間違っていないでしょうか? 例えば次のプログラムを見て下さい。
; mのn乗を計算する
m=2
n=5
answer=1
repeat n
answer=answar*m
loop
mes answer
stop
answerのつづりが間違っていますが、エラーメッセージは表示されません。命令語のつづりが間違っていればコンパイルした時にチェックされますが、変数名はそうではありません。他の言語では、プログラムの先頭で変数名を宣言しておけば、宣言していない変数を使えばチェックされるものもあります。HSPの場合answarもまた1つの変数であるものとして認識されます。answarにはデフォルトで0が入っているので、答も0になってしまいます。
どこもつづりが間違っていない場合も、自分が想定した動きとは違う書き方をしているはずですのでよく読みなおします。
(3)マニュアルをよく読む
HSPのヘルプ、拡張プラグインの説明書をよく読んで命令の使い方を誤解していないか確認します。
(4)インターネットで検索する
ヘルプやReadmeを読んでも、命令の使い方がよく分からないことがあります。そういう場合、詳しく説明しているサイトがないか、インターネットで検索するといいです。
(5)変数を表示する
プログラム実行中の変数の値を見ることは非常に有効な手段です。
-
間違った命令を入れる
111111+222222+333333+444444を計算する以下のプログラムを実行させたところ、4111110と表示されてしまいました。電卓で計算すると答は1111110になります。
dim a,4
a.0=111111:a.1=222222:a.2=3333333:a.3=444444
sum=0
sum=sum+a.0
sum=sum+a.1
sum=sum+a.2
sum=sum+a.3
mes sum
stop
そこで今どこがおかしいのか調べるために、"sum=sum+a.0"と"sum=sum+a.1"の間に"aaa"という1行を追加して実行します。
すると"aaa"という命令はありませんから、「文法が間違っています」というエラーが出てプログラムの実行が中断されます。この時HSP Debug windowが表示されますから、「変数sum」をクリックすると、この時のsumに入っている値が表示されます。まだ正常のようです。
次に"aaa"を"sum=sum+a.1"の下に移動して同じことをやります。"sum=sum+a.2"の下に移動してやってみた時に、sumが3666666というおかしな値になっていることが分かります。そこで2行目の"a.2="の後ろを見ると、3が1つ多いことに気づく、というわけです。
- dialogを使う
2次元配列を使っている場合や、HSP Debug windowの変数リストの中から目的の変数を探すのがちょっと面倒くさい場合、ダイアログボックス(メッセージを表示する小さいウィンドウ)を使うといいです。
以下は配列変数saikoro.0.0〜saikoro.0.2のそれぞれに1から6までの乱数を入れ、3つの合計を表示するプログラムですが、何度実行しても3にしかなりません。
randomize
dim saikoro,1,3
sum=0
repeat 3
rnd saikoro.0.cnt,6
saikoro.0.cnt=saikoro0.cnt+1
sum=sum+saikoro.0.cnt
loop
mes sum
stop
そこで"loop"と"mes sum"の間に以下の1行を追加して実行します。
dialog "0:"+saikoro.0.0+" 1:"+saikoro.0.1+" 2:"+saikoro.0.2
dialogの第1引数は表示させる文字列です。
何度実行しても3つとも1が入ることが分かります。そこで6行目をよく見ると、"saikoro"と"0"の間に"."がありません。
(6)人に聞く
上のような試行錯誤をしてもさっぱり分からない場合、HSP関連のサイトの質問用掲示板で聞くと、誰かが教えてくれるかもしれません。
[目次へ]|[前へ]|[次へ]