これはstrmidの実装コードです。
slen=(int)strlen(sptr);if(p1<0){p1=slen-p2;if(p1<0)p1=0;}if(p2>slen)p2=slen;sptr+=p1;ptr=p=code_stmp(p2+1);for(i=0;i<p2;i++){chrtmp=*sptr++;*p++=chrtmp;if(chrtmp==0)break;}*p=0;
そしてこれがスクリプトだとします。
mes strmid( s, i, n )
strmidが遅い理由は、文字列長を調べる必要があるのはiが-1の時だけなのに、
hsp3.1では常に文字列長を数えています。
これが遅くなった一番の理由です。
しかし問題はそこではありません。
文字列の切り出し開始アドレスを求めるところで、文字列先頭へのポインタにパラメータをただ加算しているだけです。
文字列長は全く考慮されていません。
つまり、デフォルトで半角英数63文字分確保されている変数に対して
とすると確保しているメモリ領域外をアクセスしていることになります。アクセス違反です。
;例1 s = "abc" mes strmid(s, 1024, 3)
これでOSがエラーを出さないのは読み取っているだけだからでしょう。
しかし、言語規定では確保していない領域へポインタを向けたときの動作は未定義です。
つまり安全が保障されたものではないということです。
恐らく上の例1を実行した場合、空の文字列が表示されるハズです。(つまり何も表示されない)
しかし、これはたまたまこうなっただけの偶然の出来事です。
つまりstrmidを使った場合に予想もしない値(文字列)が返ってくることがあるのです。
それを再現させましょう。
どうです?
;例2 s = "abcdefg" poke s, 3, 0 mes s mes strmid(s, 4, 10)
3行目でsに入っている『文字列』は"abc"です。
その文字列を超えた位置から10文字切り出そうというコードです。
sに入っている文字列長が考慮されていないため、ポインタを向けた先が0ではないので『文字列』があるとして値を返しました。
例2は意図的にそういう状況を作り出したのですが、
では例1で文字列先頭から1024バイト目が0でなかったらどうなっていたでしょう。
0であるという保障はありません。
その証拠をご覧いれましょう。
変な文字が表示されたのではないでしょうか?
;例3 s = "abc" mes strmid(s, 64, 3)
次にこれはどうです?
変数にsを指定しているのにxyzと表示されてしまいました。
;例4 s = "abc" m = "xyz" mes strmid(s,88,3)
このような指摘を受けて今後どのように対応されるか楽しみです。
それから、HSPTVをご覧の皆様。
この話を聞いた感想をどしどし書き込んでください。お待ちしてます。