初めて利用させて頂きます。
Delphi2009 にて次のように Form1 と Unit を新規作成しました。
「新規作成」->「VCLフォームアプリケーション」
「新規作成」->「ユニット」
Unit2 は、共通で使用するユニットと仮定し、Form1の uses で指定していま
す。Unit2 に次を宣言します。
type
// 文字列型を宣言
SJISString = type AnsiString(932); // Shift-JIS(CP932)
EUCJPString= type AnsiString(20932); // EUC-JP(CP20932)
JISString = type AnsiString(50220); // iso-2022-jp (JIS)
Form1に TEdit と TButton を配置し Button1のクリックイベントで次のようにコーディングしました。
procedure TForm1.Button1Click(Sender: TObject);
var
sjis: SJISString;
jis: JISString;
begin
sjis := Edit1.Text;
jis := sjis;
ShowMessage(IntToStr(StringCodePage(sjis)));
ShowMessage(IntToStr(StringCodePage(jis)));
end;
実行(F9)にて実行しクリックすると、「932」「50220」と正常に表示されます。
この直後に Unit1のコードをなんでもいいので変更状態します。
(スペースを入れる、コメントを追加するなど)
そしてもう一度実行(F9)をすると、「932」「932」になってしまいます。
この後にプロジェクトの再構築(Shift+F9)を行うと、「932」「50220」になります。
今まで(Delphi7)デバッグは全てF9で行っていたのですが、2009では毎回再構築をしなければいけないのかと、困惑しております。
この動作が仕様なのか、Delphiの問題なのか、設定次第で変更可能なのかを教えて頂けないでしょうか?
以上、宜しくお願い致します。
すいません。環境を書き忘れていました。
◆OS
Windows XP Professional Version 2002 Service Pack 3
◆Delphi
Delphi 2009 Professional Version 12.0.3420.21218
Delphi and C++Builder 2009 Update3
Delphi and C++Builder 2009 Update4(Database Pack Update)
Delphi and C++Builder 2009 Help Update 1
以上
当方では件の現象が発生しませんでした。
ただ、コードページを指定したハズの AnsiString が、
デフォルトのコードページになるケースがあります。
それは、"文字列が空の場合" です。
参照カウンタが 0 の場合には、指定したコードページではなく、
デフォルトのコードページが返ります。
これは参照カウンタが 0 の場合には変数を保持するペイロードが
メモリ上に存在しないために起こります。
http://homepage1.nifty.com/ht_deko/tech014.html#tech042
http://homepage1.nifty.com/ht_deko/tech018.html
このため、コードページを確認するには、
StringRefCount() で、参照カウンタを事前に調べる必要があります。
if StringRefCount(jis) <> 0 then
ShowMessage(IntToStr(StringCodePage(jis)))
else
ShowMessage('Unknown');
DEKO様、検証ありがとうございます。
私の場合もう1台のPCでも発生してしまいました。
(Delphi 2009 Professional Version 12.0.3210.17555)
そちらは何故か2回目のコードページは932ではなく0でしたが。
(デフォルトの0になってるって事ですね)
文字列は "Edit1" がそのまま入っています。
日本語を入力しても同じでした。
StringRefCount のコードを入れてみましたがやはり932でした。
ちなみに次のように処理前にTypeで宣言すると問題なく表示されます。
procedure TForm1.Button1Click(Sender: TObject);
type
SJISString = type AnsiString(932); // Shift-JIS(CP932)
EUCJPString= type AnsiString(20932); // EUC-JP(CP20932)
JISString = type AnsiString(50220); // iso-2022-jp (JIS)
var
sjis: SJISString;
jis: JISString;
以上です。
いやいや...再現しますね、このコード。
> この直後に Unit1のコードをなんでもいいので変更状態します。
この状態だと、何故か参照カウンタが 2 になってしまいます。
(再構築後は参照カウンタが 1 になります)
この件はバグっぽいので、QC入れておきます。
DEKO様、了解しました。
一応これで解決とさせて頂きます。
ありがとうございました。
以下は検証途中のものでしたが、折角ですので追加させて頂きます。
================================================================
StringRefCount の動作を追いかけようと、ライブラリパスに
"C:\Program Files\CodeGear\RAD Studio\6.0\source\Win32\rtl\sys"
を追加してコンパイルすると…
[DCC 致命的エラー] Variants.pas(1071): F2092 ユニットまたはプログラム 'Variants' が自分自身を参照しています
循環参照?
良く分かりませんが StringRefCount 自体は関係ないような気もします。
以下、StringRefCount を参考にして作ってみました。
procedure TForm1.Button1Click(Sender: TObject);
var
sjis: SJISString;
jis: JISString;
RefCount: integer;
function GetBytes(const S: RawByteString): string;
var
p, Counter, Count: Longint;
CodePage, Size: Word;
i: integer;
begin
p := Longint(S);
if p <> 0 then
begin
CodePage :=PWord(p - 12)^; // コードページ
Size := PWord(p - 10)^; // 要素サイズ
Counter := PLongint(p - 8)^; // 参照カウンタ
Count := PLongint(p - 4)^; // 要素数
ShowMessage(Format('CodePage=%d Size=%d Counter=%d Count=%d', [CodePage, Size, Counter, Count]));
Result := '';
for i := 0 to Size * Count - 1 do
if Result = '' then
Result := IntToHex(PByte(p + i)^, 1)
else
Result := Result + ':' + IntToHex(PByte(p + i)^, 1);
end;
end;
begin
sjis := Edit1.Text;
jis := sjis;
ShowMessage(GetBytes(jis));
end;
面白いですね。
問題とはあまり関係ないですが。
ツイート | ![]() |