1

2 つの COM DLL を参照するアプリがあります。アプリが起動時に呼び出す 2 つの DLL に Init 関数があります。

どちらの DLL もほぼ同じですが、uid とインターフェイス名が異なります。それとは別に、ロジックは同じです....そして使用される変数も同じです。

これがこのシステムの仕組みです - 1. StartApp() 2. Init DLL1(appVar1,appVar2)..ここで、アプリはこの DLL で定義された変数 x、y をアプリから渡された値に設定します。x = appVar1 および y = appVar2 としましょう。x と y はグローバル変数です。3. Init DLL2(appVar1a,appVar2a)...アプリは、DLL2 で定義された var x をアプリから渡された値に設定します。x = appVar1a; y = appVar2.

DLL1 で何かを実行しようとすると、 x と y の値が不思議なことに別のものに変更されました。

x は appVar2 になり、y は空白になります。

ここで、x、y、およびアプリによって InitDLL 関数で渡される appVar1 などのすべての変数は BSTR です。

私はコードをステップ実行しました...x、yはInitDLL1でappVar1、appVar2に適切に設定されています。しかし、この関数が戻り、2 番目の DLL (InitDLL2) を初期化すると、これが変わります。

興味深いことに、DLL2 ではそのような問題は見られません..コード/ロジックは非常に似ていますが..それが呼び出すインターフェイスを除いて..

DLL1 と DLL2 の両方で、InitDLL 関数で、さまざまな関数で x と y を使用する新しいスレッドを作成します。上記の問題により、DLL1 は常に失敗しますが、DLL2 には問題はありません。

何が間違っている可能性があるかについての手がかりはありますか?

4

1 に答える 1

0

BSTR を割り当てるだけではなく、コピーする必要があります。問題は次のとおりです。

// caller - by COM memory management rules, for [in] parameters
// caller needs to allocate and free the memory
BSTR str = SysAllocString("..."); // string is allocated
comObjectPtr->Init(str);          // in the function, pointer is copied to global
SysFreeString(str);               // string released, pointer points to garbage

// callee
ComObject::Init(BSTR str)
{
    // wrong code!!! you have no idea about lifetime of str,
    // so you can't just assign it. When the caller function
    // exits, string memory is released and your global is thrashed
    // I suspect you use some BSTR wrapper (bstr_t or CComBSTR) so
    // you don't see the deallocation part and that's why the values
    // are invalidated on function exit: the destructor of BSTR wrapper
    // does its job
    global_str = str;             

    // correct code:
    // global_str = SysAllocString(str);
}
于 2012-12-04T08:28:02.870 に答える