10

これを行う正しい方法は何ですか:

_bstr_t description;
errorInfo->GetDescription( &description.GetBSTR() );

また:

_bstr_t description;
errorInfo->GetDescription( description.GetAddress() );

ここIError:GetDescriptionで、次のように定義されます。

HRESULT GetDescription (BSTR *pbstrDescription);

私はこれを簡単に行うことができることを知っています:

BSTR description= SysAllocString (L"Whateva"));
errorInfo->GetDescription (&description);
SysFreeString (description);

ありがとう

4

6 に答える 6

8

The BSTR is reference counted, I seriously doubt that will work right if you use GetAddress(). Sadly the source code isn't available to double-check that. I've always done it like this:

BSTR temp = 0;
HRESULT hr = p->GetDescription(&temp);
if (SUCCEEDED(hr)) {
    _bstr_t wrap(temp, FALSE);
    // etc..
}
于 2010-12-03T15:39:45.407 に答える
4

@Hansの答えをフォローアップするには、適切な構築方法は、自分が所有しているものを返すか、解放する必要のないメモリを参照するものを 返す_bstr_tかによって異なります。GetDescriptionBSTR

ここでの目標は、コピーの数を最小限に抑えることですがSysFreeString、返されたデータを手動で呼び出すことも避けます。これを明確にするために、示されているようにコードを変更します。

BSTR temp = 0;
HRESULT hr = p->GetDescription(&temp);
if (SUCCEEDED(hr)) {
    _bstr_t wrap(temp, false);    // do not copy returned BSTR, which
                                  // will be freed when wrap goes out of scope.
                                  // Use true if you want a copy.
    // etc..
}
于 2010-12-03T16:41:42.723 に答える
4

以前の(または後の)バージョンのVisualStudioには適用されない可能性のある遅い回答。ただし、VS 12.0にはインラインの実装があり、バージンを呼び出す_bstr_tと、明らかに内部Data_tインスタンスが1で作成されます。したがって、最初の例のライフサイクルは問題ないように見えます。m_RefCountGetBSTR()_bstr_t_bstr_t

_bstr_t description;
errorInfo->GetDescription( &description.GetBSTR() );

ただし、_bstr_tがダーティの場合、既存の内部m_wstrポインタが上書きされ、参照していた以前のメモリがリークします。

以下を使用することにより、最初にを介してクリアされoperator&たダーティを使用できます。オーバーロードは、;の代わりにアドレス演算子を使用するという便利さも提供します。_bstr_tAssign(nullptr)GetBSTR()

BSTR *operator&(_bstr_t &b) {
    b.Assign(nullptr);
    return &b.GetBSTR();
}

したがって、最初の例は代わりに次のようになります。

_bstr_t description(L"naughty");
errorInfo->GetDescription(&description);

comutil.hこの評価は、VS12.0からのものに基づいています。

于 2016-07-19T04:38:27.767 に答える
1

_bstr_t(およびそのATL兄弟CComBSTR)は、BSTRのリソース所有者です。コードからスパイすると、「GetAddress」は、クライアントがBSTRを解放することが予想されるBSTR出力パラメーターを操作するユースケース向けに特別に設計されているようです。

_bstr_tがすでにBSTRを所有している場合、「GetAddress()」を使用することは「&GetBSTR()」を使用することと同じではありません。MSDNの状態:'既存の文字列を解放し、新しく割り当てられた文字列のアドレスを返します。'

_bstr_t bstrTemp;
HRESULT hr = p->GetDescription(bstrTemp.GetAddress());

警告:「GetAddress」のこの特定のユースケースは、ドキュメントに記載されていません。これは、ソースコードとそのATLカウンターパートCComBSTRの経験からの私の推測です。

ユーザー「caoanan」がこの解決策に疑問を呈したので、ここにソースコードMicrosoftを貼り付けます。

inline BSTR* _bstr_t::GetAddress()
{
    Attach(0);
    return &m_Data->GetWString();
}

inline wchar_t*& _bstr_t::Data_t::GetWString() throw()
{
    return m_wstr;
}

inline void _bstr_t::Attach(BSTR s)
{
    _Free();

    m_Data = new Data_t(s, FALSE);
    if (m_Data == NULL) {
        _com_issue_error(E_OUTOFMEMORY);
    }
}

inline _bstr_t::Data_t::Data_t(BSTR bstr, bool fCopy)
    : m_str(NULL), m_RefCount(1)
{
    if (fCopy && bstr != NULL) {
        m_wstr = ::SysAllocStringByteLen(reinterpret_cast<char*>(bstr),
                                         ::SysStringByteLen(bstr));

        if (m_wstr == NULL) {
            _com_issue_error(E_OUTOFMEMORY);
        }
    }
    else {
        m_wstr = bstr;
    }
}
于 2021-03-08T12:08:03.437 に答える
-1

私の答えも遅いです。署名があるとしますHRESULT PutDescription (BSTR NewDescription);。その場合、次のようにします

_bstr_t NewAdvice = L"Great advice!";
HRESULT hr1 = PutDescription(NewAdvice.GetBSTR());

COMの規則により、関数PutDescriptionは渡されたを変更または破棄することさえ許可されていませんBSTR

反対の場合は、関数を使用しHRESULT GetDescription (BSTR *pActualDescription);て処女を渡します。_bstr_tGetAddress()

_bstr_t GetAdvice;
HRESULT hr2 = GetDescription(GetAdvice.GetAddress());

この関数GetAddress()は、既存の文字列を解放し、新しく割り当てられた文字列のアドレスを返します。したがって、コンテンツを含むを渡すと_bstr_t、このコンテンツは解放され、失われます。_bstr_t同じを共有するすべてのsに同じことが起こりBSTRます。しかし、これは愚かなことだと思います。コンテンツを変更することになっている関数にコンテンツを含む引数を渡すのはなぜですか?

_bstr_t GetAdvice = L"This content will not survive the next function call!";
HRESULT hr = GetDescription(GetAdvice.GetAddress());

_bstr_t本物のモロンは、生に割り当てられたを渡すことさえできBSTRます:

BSTR Bst = ::SysAllocString(L"Who would do that?");
_bstr_t GetDescr;
GetDescr.Attach(Bst);//GetDescr wraps Bst, no copying!
HRESULT hr = GetDescription(GetDescr.GetAddress());

その場合GetDescr、期待値を取得しますが、の内容Bstは予測できません。

于 2020-03-12T09:55:54.737 に答える
-1
    int GetDataStr(_bstr_t & str) override {
    BSTR data = str.Detach();
    int res = m_connection->GetDataStr( &data );
    str.Attach(data);
    return res;
}
于 2021-11-30T08:47:54.557 に答える