Delphi2009 のコードページについて

解決


MASH  2009-06-11 23:25:56  No: 34701

初めて利用させて頂きます。

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の問題なのか、設定次第で変更可能なのかを教えて頂けないでしょうか?

以上、宜しくお願い致します。


MASH  2009-06-11 23:33:36  No: 34702

すいません。環境を書き忘れていました。
◆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

以上


DEKO  2009-06-12 00:00:44  No: 34703

当方では件の現象が発生しませんでした。

ただ、コードページを指定したハズの 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');


MASH  2009-06-12 00:26:41  No: 34704

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;

以上です。


DEKO  2009-06-12 00:28:11  No: 34705

いやいや...再現しますね、このコード。

> この直後に Unit1のコードをなんでもいいので変更状態します。
この状態だと、何故か参照カウンタが 2 になってしまいます。
(再構築後は参照カウンタが 1 になります)


DEKO  2009-06-12 01:19:15  No: 34706

この件はバグっぽいので、QC入れておきます。


MASH  2009-06-12 01:27:39  No: 34707

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;

面白いですね。
問題とはあまり関係ないですが。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加