1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

FPCのstringでハマりまくった件

Posted at

FPC(Free Pascal Compiler)で簡単な外部コマンドを実行した後、その戻り値が途切れる問題で一晩ハマったのでメモしておきます。

問題のコード

実行したのは、次のようなコードです。

var
  jsonResponse: string;
  jsonData: TJSONData;
begin
  jsonResponse := MyExecCommand(params);
  jsonData := GetJSON(jsonResponse);
  // …省略…
end;

少し長いJSONデータだと、必ずエラーがでます。
これ、何が問題か分かるでしょうか?

答え

問題点は、変数jsonResponseの定義がstringとなっている部分です。

今回、FPCの設定でstringがShortString(つまり、255文字以下)と定義されていたため、255字以上の文字列が壊れてしまっていたのです。これに気付くまでに一晩かかりました(T_T)

ShortStringは255以下の文字列しか扱えないという制限があります。そのため、上記のstringAnsiStringに定義を変えると問題は解決します。

ShortStringとAnsiStringの違い

ShortStringAnsiString は、Pascalで使用される文字列型で、それぞれ以下のような違いがあります。

  • ShortString --- 固定長文字列:最大長が255文字に制限されています。スタック上に配置され、メモリの再割り当てを行わないため、サイズの範囲内で高速に処理できます。
  • AnsiString --- 動的長文字列:サイズに制限がなく、メモリの許す限り長い文字列を扱えます。ヒープに配置され、メモリの再割り当てによりサイズを自動で調整します。これにより、大きな文字列を動的に扱うことが可能です。

ただし、AnsiStringは、Unicode非対応であるため、1バイト単位で文字を扱います。多言語文字が必要な場合は UnicodeStringを利用します。

FPC/Delphi/Pascalの文字列処理は、文字列型がたくさんあって、扱いが本当に複雑です。「文字列型を制する者がPascalを制する」と言って良い状況かもです。

FPCにはモードがある

なお、コンパイル指示で {$H+}を有効にすると、stringが、AniStringになります。多くのIDE環境でこれが自動で指定されているため、コマンドラインでFPCを適当に使った場合に、今回の問題に遭遇してしまいます。また、最初から「Delphi」互換モードにしておけば、stringは勝手にAnsiStringになります。

FPCには次のように多くの互換モードがあり、それぞれの違いを把握するのは非常に難しい状況です。モードによって、型が変更になるというのは、最初に知っておくべきですね。

  1. FPCモード ({$MODE FPC}):デフォルトモードで、FPC独自の構文や仕様を使用。
  2. Delphiモード ({$MODE Delphi}):Delphi互換モードで、Delphiコードの互換性を高める。
  3. OBJFPCモード ({$MODE OBJFPC}):オブジェクト指向拡張が強化されたモード。
  4. TPモード ({$MODE TP}):Turbo Pascal互換モード。

まとめ

FPC深い。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?