こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

自作DLLの引数について、ポインタ渡しが??

VS2005 VC++環境でMFCスマートデバイスDLLを作成しています(アプリ側もVS2005 VC++)。

テスト用のアプリからDLL内の文字列を引数とする関数を呼び出すと、
呼ばれた関数に正しく文字列が渡りません。
以下の場合、func1のw1はデバッガで正しく見れません。
でもw2にtcscpyは成功しw2には正しく値がセットされます。
このときにw1のアドレスがなぜか変更されます。
以下の例では引数が1つですが、2つ以上引数がある時には
その他の引数のアドレスもとびます。
func2のl1は正常に見れます。
func3のl1は正常に見れません。

ポインタ渡しするときに異常になるのですが、
原因がさっぱりわかりません。
同じことをWindowsXP用のプロジェクトを作り、
XPで確認するとどれも正常に見れます。

どなたかアドバイスをお願いします。

----------------------------------------DLL側----------------------------------------
extern "C" __declspec(dllexport) void func1(WCHAR * w1)
{
WCHAR w2[16] ;
_tcscpy(w2,w1);
return;
}

extern "C" __declspec(dllexport) void func2(long l1)
{
long l2 ;
l2 = l1 ;
return;
}

extern "C" __declspec(dllexport) void func3(long *l1)
{
long l2 ;
l2 = *l1 ;
return;
}

----------------------------------------アプリ側----------------------------------------
extern "C" __declspec(dllimport) void func1(WCHAR *);
extern "C" __declspec(dllimport) void func2(long );
extern "C" __declspec(dllimport) void func3(long *);

・・・・中略・・・・

WCHAR a[16] ;
_tcscpy(a,_T("ABC"));
func1(a);
func2(123);
long l3 = 123 ;
func3(&l3);

投稿日時 - 2009-01-25 22:33:21

QNo.4661039

すぐに回答ほしいです

質問者が選んだベストアンサー

ポインタのデータがまともに見れない点は当方でも確認できました
ただ、ポインタの指している内容はローカル変数への代入などをしてやればいいようです

DLL側のエクスポート関数の冒頭に
AFX_MANAGE_STATE(AfxGetStaticModuleState());
を記述してみてください
詳細は MFCテクニカルノートの 33および 58あたりを参照しましょう

どうも原因は最適化のオプション指定による物のようです
DLL側の設定を /Od に変更してやれば デバッガで引数の内容も見られるようです
w1,w2,w3の同一アドレスの件もこの最適化による副産物のようです

#4のお礼の件は
w1,w2,w3自体をその後加工などをしていないのが原因なのかもしれません

WCHAR w1[16] ;
WCHAR w2[16] ;
WCHAR w3[16] ;
WCHAR w4[256] = { _T("") };

wcscpy(w1,_T("AAA")); // (1)
wcscpy(w2,_T("BBB")); // (2)
wcscpy(w3,_T("CCC")); // (3)

wcscat( w4, w1 );
wcscat( w4, w2 );
wcscat( w4, w3 );

とした場合は w1,w2,w3,w4すべて別アドレスで確保されるようです

Mobileの単体EXEのみで動作するようなアプリなら 静的リンクを使うほうが一般的なのかもしれません
余分なDLLなどが必要ない分 システムに対する負荷が少なくてすみます
DLL/EXEで動作するものなら 共有DLLを使って 動的リンクを使うほうがメモリーの圧迫を抑えられるかもしれません

投稿日時 - 2009-01-27 00:15:22

お礼

redfox63様
試験までしていただいたようでありがとうございます。
DLL側の最適化オプションを/Odに変更することで、
引数の件も、w1,w2,w3が同じアドレスになる件も解消されました。

AFX_MANAGE_STATEについてはテクニカルノートを見ても難しかったので
後でじっくり勉強します。
今回はエンドユーザ(別の開発者)に提供するDLLを作成すること目的で
した。
「共有DLLを使って動的リンク」については試行して検討したいと思います。

ありがとうございました。

投稿日時 - 2009-01-27 01:04:42

このQ&Aは役に立ちましたか?

3人が「このQ&Aが役に立った」と投票しています

回答(5)

ANo.4

> MFC スマート デバイス DLL
言葉足らずで申し訳ない。
DLLの種類というのは
共有 MFC DLL を使用する通常の DLLでしょうか?
MFC拡張DLLのほうでしょうか?

最初の質問のコードを見る限りでは、
MFCを使用している感じは見受けられないのですが、
この辺りのメモリ共有の動作がなにか影響しているのではと。。。

>ポインタ渡しするときに異常になるのですが
もうひとつ。異常になるというのは、
アプリケーション例外を起こすという事でしょうか?

投稿日時 - 2009-01-26 22:28:58

お礼

aris-wiz様

DLLもアプリ側もアプリケーションウィザードでは、
デフォルトが"スタティックライブラリでMFCを使用"に
なっていたのでそのままにしていました。
DLLとアプリ側を"共有 MFC DLL を使用する"に
変更しましたが結果は変わらずでした。

質問のコードは問題をわかりやすくするために
テスト用に1から作成したものでした。
本当はXP用に作られているDLLをWindowsMobileと
CE用に移植しているところです。
XP用のDLLを確認したところ、
"共有 MFC DLLを使用する通常のDLL"で作成されていました。

アプリケーション例外にはならないのですが、
存在するファイルが_wfopenで失敗するなどが起きています。

いろいろ試していて気づいたのですが、
特に引数が問題というよりも、根本的におかしなことが
おきていました。
DLLの関数を以下のように変更して試してみました。
(これも1からDLL、アプリともにソリューションから作り直しています)

extern "C" __declspec(dllexport) void __stdcall func1(void)
{
WCHAR w1[16] ;
WCHAR w2[16] ;
WCHAR w3[16] ;

wcscpy(w1,_T("AAA")); // (1)
wcscpy(w2,_T("BBB")); // (2)
wcscpy(w3,_T("CCC")); // (3)
return; // (4)
}

(1)から(4)までステップ実行したところ、デバッガのウォッチで見たところw1,w2,w3のアドレス
と値が以下のようになります。
 (1) w1 0x221bed5c "□" (値はゴミと思われる)
   w2 0x221bed5c "□" (値はゴミと思われる)
   w3 0x221bed5c "□" (値はゴミと思われる)
 (2) w1 0x221bed5c "AAA"
   w2 0x221bed5c "AAA"
   w2 0x221bed5c "AAA"
 (3) w1 0x221bed5c "BBB"
   w2 0x221bed5c "BBB"
   w2 0x221bed5c "BBB"
 (4) w1 0x221bed5c "CCC"
   w2 0x221bed5c "CCC"
   w2 0x221bed5c "CCC"
なぜか、w1,w2,w3ともに同じアドレスを指しているため、値が変わってしまいます。

同じことを”Win32スマートデバイス"でDLLで作成すると正常に動作します。
(w1,w2,w3は別のアドレスを指し、それぞれに値が代入されます)

# テストは”JPN Windows Mobile 6 Classic Emulator”で実行しています。

投稿日時 - 2009-01-26 23:35:34

ANo.3

ちなみに、
「MFC スマート デバイス DLL 」で作成されている
DLLの種類と、アプリケーション側の設定は、
「MFC スマート デバイスアプリケーション」で
作成されているのでしょうか?それともWin32?

実はMFCスマートデバイスDLLとWin32アプリの組み合わせで
メモリの共有違反が起こっているとか。。。

投稿日時 - 2009-01-26 17:33:43

お礼

aris-wiz様、ありがとうございます。

「MFC スマート デバイス DLL 」と
「MFC スマート デバイスアプリケーション」の
組み合わせです。

なぜかわかりませんが、
「Win32スマートデバイスプロジェクト」でDLLを作成し
「MFC スマート デバイスアプリケーション」の
組み合わせだと発生しません。

すでに「MFC スマート デバイス DLL 」で作成しているので
Win32に変更せずにそのまま使える方法で解決したいです。

投稿日時 - 2009-01-26 18:16:27

ANo.2

>でもw2にtcscpyは成功しw2には正しく値がセットされます。
>このときにw1のアドレスがなぜか変更されます。

もしかすると「アプリとDLLで、引数用のメモリは同じ物理メモリを指していても、論理アドレスが違う」のかも知れません。

Windowsは、デバドラやDLLに飛んだり、プロセスが切り替わったりすると、メモリ空間がゴッソリ入れ替わるので、アプリとDLLで同じ論理アドレスを指している保証はないと思います。

投稿日時 - 2009-01-26 13:31:12

お礼

chie65535さん、ありがとうござます。

「論理アドレスが違う」とすると、
文字列渡し(ポインタ渡し)は不可ということになるのでしょうか?
文字列を実データ渡しにするにはどうすればよいでしょうか?
”const WCHAR *”も試したのですが駄目でした・・・。

投稿日時 - 2009-01-26 13:42:52

ANo.1

__stdcallをつけたらどうなりますか?

投稿日時 - 2009-01-26 08:51:41

補足

自己レスです(補足では無いのですが)。

MFCスマートデバイスDLL ではなく、
Win32スマートデバイスDLL(サポートの追加でMFCを選択)ですと
正常に動作します。

さっぱり訳がわからなくなりました・・・。

投稿日時 - 2009-01-26 10:28:40

お礼

bluecampusさん、ありがとうございます。
以下のようにしたのですが結果は変わらずでした。

DLL側
extern "C" void __declspec(dllexport) __stdcall func1(WCHAR *w1)
AP側
extern "C" void __declspec(dllimport) __stdcall func1(WCHAR *);

投稿日時 - 2009-01-26 09:08:06

あなたにオススメの質問