というのも、まず以下のスクリプトを確認していただきたいのですが
// 初期化 sdim srcstr, 64 //再確保が行われないように64バイト未満の文字列を代入 srcstr = "Hello World" //このポインタとサイズは「Hello World」のものになる p = varptr(srcstr) s = varsize(srcstr) //再確保される長さの文字列を代入 srcstr = "このマニュアルは、HSPによるプログラミング方法と言語仕様全般を解説したものになっています。初めてプログラミングに挑戦するという人は、最初に「初心者のためのHSP入門」を 読むことをお勧めします。 " //再確保前の「Hello World」のポインタで内容を取り出す dupptr ptrstr, p, s, 2 //「このマニュアルは、HSPによる〜」ではなく「Hello World」のまま //「このマニュアルは、HSPによる〜」のポインタを得る p2 = varptr(srcstr) s2 = varsize(srcstr) //「このマニュアルは、HSPによる〜」よりも長い文字列を代入してさらに再確保させてみる srcstr = "ある程度プログラミングの経験がありHSPが初めてという方は、 このクイックスタートをお読みいただいて実際に使ってみることをお勧めします。使っている過程でわからないことが出てきたら、このマニュアルを検索したりヘルプブラウザを活用したりして 調べてみてください。" // 再確保前の「このマニュアルは、HSPによる〜」のポインタからdupptr dupptr ptrstr2, p2, s2, 2 //これは謎の内容になる //最初の「Hello World」のポインタから再度dupptr dupptr ptrstr3, p, s, 2 //これは HelloWorld のまま //srcstrに64バイト未満の文字列を代入してみる srcstr = "Hot Soup Processor" //さらにdupptr dupptr ptrstr4, p, s, 2 //「Hot Soup Processor」 にはならず Hello World のまま //(「Hot Soup Processor」が64バイト未満だからといって元々のポインタの変数に代入されることはない) dialog "待機1" // srcstrを最初のサイズを超えるサイズで初期化 sdim srcstr, 128 //この時点で ptrstr、ptrstr2、ptrstr3、ptrstr4は依然として内容が残る。 dialog "待機2" sdim srcstr, 64 //この時点で ptrstr2 以外の内容はクリアされる stop
このスクリプトにおいて最初の「Hello World」が代入された時点のポインタはその後サイズの再確保が行われても有効だということが分かります。
よって「Hello World」という文字列と「このマニュアルは、HSPによる〜」という文字列はメモリ上で干渉していないということが分かります。
しかしそれはつまり、文字列型変数のサイズの再確保が行われた際に古い内容は依然としてメモリ上には残り続けているということになると思います。
またsdim srcstr, 128でもこれらの内容はメモリ上に残り続けています。
ですが最後のsdim srcstr, 64でこれら一切の内容がクリアされています。
これらの挙動は変数を配列型にして各要素に同様の処理を行っても同じ結果となりました。
以上の点を踏まえて考察すると、
・文字列変数はsdimで初期化されたサイズを超えない文字列はそのまま代入される。
・sdimで初期化されたサイズを超える内容が代入されるとき、メモリ上に別の内部的な文字列変数を確保しそこに新規内容を代入する。
この際元の変数そのものには処理は何も行わずに、元の変数へのアクセスは新規の内部的な変数へリダイレクトされる。
・sdimで初期化されたサイズを超える内容が内部的な変数へ代入され、さらにそれをも超える内容が代入されるとき、再度新たに内部的な変数が確保され 以前の内部的な変数は破棄される。
・sdimで最初に初期化したサイズを超えるサイズで初期化した場合、内容はメモリ上に残り続ける。
・sdimで最初に初期化したサイズ以下のサイズで初期化した場合、内容はクリアされる。
ということになると思います。
(「内部的な変数」というものは、単にCでの char *p = "文字列"; と同じことなのかもしれませんが)
私感ですが、この仕様はかなり厄介だと思います。
これってつまり、「文字列型変数は『最初に初期化したサイズ以下のサイズで再初期化する』か『最初に初期化したサイズに収まる文字列しか扱わない』以外では残骸がメモリ上に残り続ける」ということですよね?
もちろんコーディングしてる人それぞれでバラバラだと思いますが、この条件に当てはまるほどキチンとした使い方をしている人は少ないのではないでしょうか。
となると、コード中でsdimで文字列型変数を初期化する際に動的なサイズ(def(c)funcの文字列型パラメータをstrlen()するなど)で初期化するのは避けるべきな気もします。
プログラミングマニュアルやリファレンスではあらかじめsdimでサイズを指定して変数のサイズを確保を推奨していますが、もし再度sdimで初期化する際にサイズが最初に初期化したサイズを超えるようではそれでリークが発生することになります。
文字列ならまだしも、HSPはバイナリの読み込みもsdimで行うので、数メガバイトのファイルを読み込んだ場合はその分リークするということだと思います。