The Delphi Bug List

Entry No.
424
VCL - 一般 - INIファイル - TIniFile
TIniFile.WriteInteger と TIniFile.WriteString とに空白文字で終わるセクション名を渡すと、"an invalid page fault in module KRNL386.EXE at 0002:00005c53" が発生する
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 4.03 5.0 5.01 6.0 6.01 6.02 Kylix 1.0
Absent Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha N/A
解説
Reported by Alan M. Cohen; checked by Reinier Sterkenburg
Jordan Russell、Eddie Churchill(Borland)、Erwin Dokter により、この'バグ'に付いての追加情報が提供されています。

#676 も参照してください。

このバグは、ボタンクリックに以下のコードを記述することで確実に再現できます。
  IniFile := TIniFile.Create('Test.ini');
  IniFile.WriteString('Test ', 'Key1', 'Val1');
  IniFile.Free;
2行目の引数 'Test ' の最後の文字が ' ' という点に注意してください。' ' を削除すると、この問題は発生ません。
Erwin Dokter 解説:
Delphi 1 でこのバグが発生しない理由は、Delphi 1 が型キャスト PChar を使用しないためです。Delphi 1 では、PChar 型の引数を必要とする API 関数の呼び出しには、string を PChar に変換するために以下のような手法を用いていました。
function SomeCall(const parm: string): Word;
var
  buf: array[0..255] of Char;
begin
  SomeApiCall(StrPCopy(buf, parm);
end;
Delphi 2 では型キャスト PChar が導入されたため、呼び出しは次のように変更されました:
function SomeCall(const parm: string): Word;
begin
  SomeApiCall(PChar(parm));
end;
これは Delphi 2 で起こっていることをうまく説明します。WritePrivateProfileString は型キャストされた定数の後ろの空白を取り除こうとしており、そのためにページフォルトが発生しています。Delphi 1 のように本当の PChar を渡せば問題は起こりません。

その他の注意:
  1. このバグは Windows のバージョンに依存します:Windows 95 と 98 ではバグが発生しますが、NT 4.0 SP3 では(セクション名から空白文字が取り除かれる場合でも)問題ありません。NT でこのバグが起こらないのは、WritePrivateProfileString が独自のバッファを使用するためです。
  2. TIniFile.WriteBool は WriteString を呼び出しているため、このバグを継承しています。
  3. WriteString は WritePrivateProfileString を使用しており、かつ、(MSDN によれば)先頭の引数には空白文字を許可していないように見えます。そこには大文字と小文字とを含むことができると書かれていますが、実際には数字でも正常に動作するように見えます。WritePrivateProfileString を呼ぶ前に Delphi がすべての空白文字を取り除くべきですが、当面はユーザが空白文字の使用を避けるべきです。
解決策 / 回避方法
INI ファイルのセクション名の最後に空白文字を使用することは避けてください。それより良い方法は(今のところ?)ありません。
Latest update of this entry: 2002-03-18
本家 The Delphi Bug List のエントリーはこちら
The Delphi Bug List 日本語訳 へ