_bstr_tをDLLの引数にして使用するには?

解決


とびうお  2007-10-25 06:41:26  No: 66641

こんばんは。
C++をはじめて間もない者です。
_bstr_tの使い方でどツボにはまってしまいましたので、質問させて頂きます。

XMLファイルのアクセスを行うクラスを「.lib」で作成し、
それを使用してXMLファイルへのアクセスを行っていました。
無事に取得出来ることを確認し、この.libの処理を.dllへ移行して使用するようにしたのですが、ここで問題が発生いたしました。

XMLより文字列を取得する関数で引数に_bstr_tを使用しているのですが、
なぜか複数回(2回目以降)呼ぶと以下のようなエラーが発生するようになってしまいました。(debugモードにて確認)

何が原因かがつかめず先に進めなくなってしまいました。
そもそも、_bstr_tの使い方が間違っている可能性もあると思いますが、
よろしくご教授お願いいたします。

-------------------------------------------------------
Debug Assertion Failed!
〜省略〜
File: dbgheap.c
Line: 1011

Expression: _CrtIsValidHeapPointer(pUserData)
-------------------------------------------------------

以下、テスト的に作成したプログラムです。
DLL側:
DWORD CTest::GetBSTR(_bstr_t &bstrVal)
{
  bstrVal.operator =("Test");
  return 0;
}

呼び出し側:コンソールアプリ
int main(int argc, char* argv[])
{
  CTest test;
  _bstr_t bstrVal;
  
  for(int i=1; i < 100;i++){
    test.GetBSTR(bstrVal);
    printf("%d BSTR=[%s]\n",i,(char*)bstrVal);

  }
  printf("end\n");
  return 0;
}


どら  2007-10-25 08:45:59  No: 66642

論点がずれているかもしれませんが・・・

DWORD CTest::GetBSTR(_bstr_t &bstrVal)
ではなく
DWORD CTest::GetBSTR(_bstr_t *bstrVal)

にして

test.GetBSTR(bstrVal);

test.GetBSTR(&bstrVal);

では?
引数で変数やクラスのアドレスを参照させるならこうですよね?


どら  2007-10-25 08:47:12  No: 66643

補足。

質問をするときには、開発環境も記載した方がよいと思います。
VCだと仮定しても、バージョンによって回答内容が異なる場合もありますので・・・


wclrp ( 'o')  2007-10-25 08:52:43  No: 66644

大丈夫だとは思うけど
ヘッダファイルに定義されているものだから
EXEとDLLで_bstr_tの中身が変わっていたらやだなあ。
異なる動作をしたらトラブル起こすよ。

bstrVal.operator =
じゃなくて
bstrVal =
でいいはずだけど。

EXEとDLLでデバッグ版とリリース版あるいは
MFC??.DLLあるいはそのほかのDLLかDLLではないライブラリ
などが混在すると
別の実態がメモリ確保と解放をおこなうので問題になるよ。

DLLにするなら互換性のあるBSTRにすべき。


とびうお  2007-10-25 21:05:17  No: 66645

みなさま、おはよございます。
レスありがとうございます。

どら様のおっしゃっている内容にて確認してみましたが、結果は変わりませんでした。

wclrp ( 'o') 様
>DLLにするなら互換性のあるBSTRにすべき。
こちらの方向で考えて行きたいと思います。
それと
>別の実態がメモリ確保と解放をおこなうので問題になるよ。
なのですが、別の実態とはどのようなことなのでしょうか?
たしかに、2回目の関数を呼んで_bstr_tに文字列を入れる時にその領域を一度deleteしててその時にアサートがでている感じです。
なんかまずいことが起きているとは思うのですが・・・(以下のdeleteです)
ーーーーー-------------------------------------------------
inline unsigned long _bstr_t::Data_t::Release() throw()
{
  if (!InterlockedDecrement(reinterpret_cast<long*>(&m_RefCount))) {
    delete this;  <-ここです
    return 0;
  }

  return m_RefCount;
}
ーーーーー-------------------------------------------------

ちなみに、開発環境は以下のとおりになります。
Windows2000、VS6.0。
DLL側:Win32 Dynamic-Link Library(ビルド環境はdebug)
EXE側:Win32 Console Applecation(ビルド環境はdebug)


tetrapod  2007-10-25 22:56:41  No: 66646

http://madia.world.coocan.jp/cgi-bin/Vcbbs/wwwlng.cgi?print+200710/07100022.txt
と同じことが bstr_t の中で起こっているわけだ

なので、EXE/DLL をまたがるインターフェイスに使う型としては
コンパイルオプション等によらず互換性がある (ありそうな) 単純な型が良い、
ということなわけ。

DLL と EXE でスレッドモデルが違ったりしてないか?
DLL 開発完了後に行う、別の EXE の開発の際に VS2005 等に乗り換えたりしないか?
その DLL を他人に使わせる可能性は無いか?
その他人は BCC や GCC で開発したりはしないか?ということだ


とびうお  2007-10-26 22:20:39  No: 66647

tetrapod様、ならびにレスくださった方々。
ありがとうございました。

とりあえず、DLLにするか、LIBのままにするか検討して対応して行きたいと思います。

いまの段階だとDLLのパラメータを互換性のある型にする方向です。


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

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






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