この文章は gt4f90io の前身である gtool4 Fortran90 Tools/Library における文字列の扱いについて記されたものです (最終更新: 2001年09月25日 豊田英司)。
gt4f90io は gtool4 Fortran90 Tools/Library の設計や思想、 ソースコード そのものなど多くのものを引き継いでいますが、 この可変長文字列に関して は、(主に gt4f90io の作者の力不足ゆえ) gt4f90io では考慮しないこととし ています。 ただ、ソースコードをそのまま引き継いでいる部分も多いため、 可変長文字列のための構造体VSTRINGは gt4f90io 内に残っています。 そのた め、参考として以下の文書をここに残しておきます。
Fortran の文字型は固定長文字列です。つまり、コンパイル時に長さの決まっ た文字列を扱います。しかしながら、実際の文字処理ではファイル名、変数名 などのように長さが実行時にならないとわからない文字列を取り扱うケースが 多くあります。このようなばあい、どのようにコーディングするのがよいのか について議論します。
Fortran の立場では、文字型はひとつの型ではなく、長さというパラメタが異 なる型たちの総称です。そのため文字型変数の長さはコンパイル時に決定して しまうのです。
長さの異なる文字型どうしの演算については以下のような規則があります。
したがって、文字列を取り扱う際には常に文字型変数の長さを十分大きくとる ようにしておけば、文字型の値を代入しても Fortran 的には同値の(つまり a == b となるような)文字列が得られることは保証されます。しかし、同値 性は失われないとはいっても、印字するときなどに文字列の末尾に余計な空白 が何十文字〜何百文字も表示されるのは迷惑です。このような場合のために、 TRIM 組みこみ関数を用いて末尾に空白を含まない最小限の文字列を得ること ができるようになっています。
このようなアプローチによるコーディングの得失を下表にまとめます。
準備がいらない
余計なアクセスルーチンなどが不要で効率がよい可能性が高い
文字列長が短過ぎるとプログラムが入力によっては文字列末尾を切り捨て てしまう不具合を発生しやすい
プログラム単位ごとに文字長を指定しなくてはならないため、文字長を一 貫して変更することが困難
プログラマが根拠もない文字長をハードコードすることがままあるため、 品質保証が困難
Fortran 90 (ISO 1539-1:1991) の導入後、補助規格 ISO 1539-2:1994 という ものが制定され、任意の長さの文字列を表現できる type(VARYING_STRING) 型 とそれにアクセスする手続の仕様を決めています。
扱える文字列の上限をサブルーチンごとに明示する必要がなく、仕様保証 が容易になる
実行時に変化する文字長を保持できる
文字列を返す関数を作ったとき、結果に TRIM をかけなくても末尾の余計 な空白がつかないためすぐに他の演算で使える
ほとんどの Fortran 処理系で実装されていないので自分で用意する必要がある
規格のインターフェイスをコンパイルできないようなバグのある処理系が たくさんある
規格が例示する実装は大抵メモリリークする
比較演算子は組込み文字型と同じ動作で、末尾空白は結局無視されている
このようなアプローチでは、プログラマは扱う文字長の上限を明示する必要が ありません。従って文字長の上限によってプログラムの動作に不自然な制約を 課する必要がなくなります。また、プログラムの仕様変更に伴ってプログラム のあちこちを修正して回る危険もありません。このことはライブラリを自分で コンパイルしなければならない欠点を補ってあまりあるように思われます。
規格の付属書で例示された実装が「メモリリーク」する(ポインタ配列に allocate を行った後 deallocate しない)という問題は広く知られています が、扱える文字長に上限を与える実装は禁止されていないので、固定長バッファ を用いて一切 allocate を用いない実装によって、まがりなりにも *1 規格に合致しながらメモリリークを起こさない実装を作ることができます。
そこで、gtool4 ライブラリでは固定長バッファ方式で ISO_VARYING_STRING インターフェイスを実装してこれを内部処理で積極的に用いてきました。しか しながら、非常に残念なことに、ISO_VARYING_STRING インターフェイスには 処理系のバグによる移植性の問題があることがわかってきました。
ほとんどすべての言語処理系にはバグがあるものです。そして、よくテストさ れていない機能にはほとんど使い物にならないほどのバグがあるものです。著 者の身近な環境では、以下のような問題が発生しました(理由は推測)。
このような問題への対処としてインターフェイスを変える場合、 (ISO_VARYING_STRING が将来有望であったとすればなおさら)インターフェ イスモジュールを同名にするのは混乱の元です。
そこで、現在次のような対策が検討されています。
アプリケーションプログラムが十分な移植性を確保することはソースコードレ ベルで流通するソフトウェアに不可欠な条件です。コンパイルを行うユーザが システム依存な修正を適切に行えるほど確実な知識と暇を兼ね備えなければな らないという要求は理不尽なものだからです。
一方、ISO_VARYING_STRING インターフェイスが顕在化させた処理系のバグは、 理由が推測できるようなものでした。そこで、以下のような対策によってライ ブラリを修正する事にします。
可変長文字列を使わなければならない目的として文字列末尾の空白を無視でき ない用途をあげるのはあまり現実的ではない。ISO_VARYING_STRING はそのた めに必要な比較演算子すら用意していないからである。してみると、可変長文 字列型を用いる目的としては文字長をプログラム中にハードコードしないで済 むということが最重要であると考えられる。このような見地から、以下のよう な指針をたてることができる。
*1
注: 「まがりなりにも」というのは、処理系に扱えるプログラムの大きさあ
るいは複雑さに実装が上限を課することは規格上許されているため、固定長バッ
ファを用いる実装をもって処理系とみなし、ある程度以上大きい文字列は扱え
ないのだと言い張れば規格合致処理系だという程度のことです。実用上は充分
有益ですが、あまり誉められた話ではありません。なお、Fortran 95 準拠の
新しい ISO 1539-2:1999 で例示されている ISO_VARYING_STRING モジュール
実装例ではFortran 95 の構造体成分初期化機能を用いてメモリリーク問題が
相当低減されています。唯一のメモリリークの可能性は VARYING_STRING 型を
返す関数の結果を他の手続の引数として使用するときだけです。残念ながら、
この問題だけは当面解消しない公算が大きいように思われます。