DelphiとVCでの共有メモリでの開始アドレスのずれ??

解決


ゆう  2012-05-14 22:51:03  No: 42171

DelphiとVCの各プロセスで、メモリ共有のためMapViewOfFileを使用して、開始アドレスを取得します。

○Delphi側
レコード型のポインタを使用して、配列で管理
TFile = Record
  m_arr array[0..100] of integer;
end;

tf :^TFile;

tf := MapViewOfFile(      )

tf.m_arr[1] := 7

○VC側
ポインタで管理
LPVOID cMap;
int *cm;

cMap = ::MapViewOfFile(      )
cm = (int *)cMap;
*(cm +1) = 7

このとき、例えば*(cm+10) = 5 とVCでした場合、
Delphi側で期待しているのはtf.m_arr[10] = 5の値ですが、
tf.m_arr[8] が 5になります。
このずれがなぜ生じてしまうのかわかりません。

考えられることありますか?
また開始アドレス自体が同じかどうか調べる方法ありませんか?

よろしくお願いします。


ぽむぽむ  2012-05-15 00:56:28  No: 42172

packed record かな?
http://srgia.com/docs/dbl/DelphiBugList0623.html


ゆう  2012-05-15 01:17:03  No: 42173

ありがとうございます。
そーゆうこともあるんだと知れました。
ですが今回のケースは違うようです。

packed を追記しましたが、結果は変わりませんでした。


Mr.XRAY  2012-05-15 02:44:15  No: 42174

こんにちは.Mr.XRAYです.

>また開始アドレス自体が同じかどうか調べる方法ありませんか?

VC側で作成した共有メモリのと,Delphi側のそれと,という意味でしたら,
違いますよ.きっと.多分.
Delphi側というより,Aというアプリで,共有メモリを作成したとします.
でも,他のアプリでは,Aというアプリが共有メモリを作成したぞ! 
ということを知ることはできないのではないかと思われますから.

もしからしたら,同じアドレスに割り当てることができるかも知れませんが,
ちょっと分かりません.
もっとも,同じだったら困ることになると思うのですが.

これ以上は,何とも.
ちょっと前に,レコード型のメンバーの数を知りたい,という質問がありましたが,
実際にはそうではなかった,という痛い目に会いましたので.


Mr.XRAY  2012-05-15 02:53:11  No: 42175

あれま,ゴメンなさい.読み返したら,違うんですね.
共有メモリに,他のアプリからアクセスする話なんですね.失礼しました.


Mr.XRAY  2012-05-15 03:05:13  No: 42176

実際に確認可能なコードがないので,確実なことは言えませんが,
VCの型とサイズ,Delphi側の型とサイズの問題かも知れません.


KHE00221  2012-05-15 06:59:32  No: 42177

MapViewOfFile が  返す値が  アドレス


ゆう  2012-05-15 18:52:29  No: 42178

ありがとうございます。

訂正があります。
> Delphi側で期待しているのはtf.m_arr[10] = 5の値ですが、
> tf.m_arr[8] が 5になります。
と書きましたが、VC、DelphiともにIntの場合は
tf.m_arr[9] が 5になります。

KHE00221さんの言うとおり、
MapViewOfFileの返す値が開始アドレスだと認識しているので、
どの型であろうと
*cm と tf.m_arr[0] は等しい値になりませんか?


ws  2012-05-15 23:16:24  No: 42179

int型だとわかりにくいのでchar型で実験してみては
また逆のパターン(Delphiで書きこみしてVCで読み込み)も
検証してみたら原因がつかめるのでは?
メモリ関係についてはVC側の方がデバッグしやすいかも。

#当方VCのコードは書けるのですがDelphiのスキルが足りないので
#検証できません。再現できるソースを載せてはどうでしょう。


ゆう  2012-05-16 00:05:24  No: 42180

Charでも試しました。
Char(VC) - ShortInt(Delphi) で行うと

例えば
VCでcm+5 = 5            →  Delphiでtf.m_arr[1] = 5となり。
Delphiでtf.m_arr[8]=8   →  VCでcm+12 = 8  となります。
4要素分ずれますね。

うーんShortでやると2要素分ずれるので、
結果4バイトずれてることになりますね。


au  2012-05-16 02:01:03  No: 42181

下記コードで実験してみましたけど特にずれは無かったですね。

Delphi側
  PData = ^TData;
  TData = record
    Data: Array[0..10] of Byte;
  end;

const
  SFILEMAP_TEST = 'FILEMAP_TEST';

procedure TForm1.FormDestroy(Sender: TObject);
begin
  if FHMap <> 0 then
  begin
    CloseHandle(FHMap);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FHMap := CreateFileMapping(INVALID_HANDLE_VALUE, Nil, PAGE_READWRITE, 0, 1024, SFILEMAP_TEST);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  p: PData;
begin
  if FHMap <> 0 then
  begin
    p := MapViewOfFile(FHMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
    ShowMessage(IntToStr(p.Data[1]));
    UnmapViewOfFile(p);
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  p: PData;
begin
  if FHMap <> 0 then
  begin
    p := MapViewOfFile(FHMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
    p.Data[1] := 5;
    UnmapViewOfFile(p);
  end;
end;

VC側ダイアログアプリ

コンストラクタで
m_hMap = ::CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, 1024, _T("FILEMAP_TEST"));
デストラクタで
if (m_hMap) 
   CloseHandle(m_hMap);

void CMapFileDlg::OnBnClickedButton1()
{
  LPVOID pMap;
  if (m_hMap)
  {
    pMap = MapViewOfFile(m_hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
  char* pC = PCHAR(pMap);
    UnmapViewOfFile(pMap);
  }
}

void CMapFileDlg::OnBnClickedButton2()
{
  LPVOID pMap;
  if (m_hMap)
  {
    pMap = MapViewOfFile(m_hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
  char* pC = PCHAR(pMap);
  pC[2] = 10;
    UnmapViewOfFile(pMap);
  }
}


tor  2012-05-16 05:55:34  No: 42182

> どの型であろうと
> *cm と tf.m_arr[0] は等しい値になりませんか?
レコードの先頭=配列の先頭要素のアドレスとは限りません。
本物のソースではm_arrが動的配列だということはないですか?


KHE00221  2012-05-16 06:13:45  No: 42183

tf :^TFile;

m_arr[0] のアドレスを比べてごらん?


ゆう  2012-05-16 19:32:51  No: 42184

みなさん回答ありがとうございます。

色々試していましたが、
結果Record型に消したはずの4バイトの型宣言がm_arr の前にありました。
それは4バイトずれますね…。
ポカですいません。

ただメモリに関して色々ためしたので、非常に勉強になりました。
また何かありましたらよろしくお願いします。


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

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






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