0

I have BSTR string which is passed from COM server. When I put this string into _bstr_t (or CComBSTR) constructor then access violation is occurred. I checked this exception and found that this exception raised only when BSTR is empty (or null).

I was trying to put nulled BSTR explicitly to _bstr_t constructor and this works fine:

BSTR bstr = NULL;
_bstr_t t(bstr, false); 

cout << t.length() << endl;

But with BSTR which is passed from COM server this don't work - access violation exception is ocurred when string is empty or null (or maybe corrupted?)

I found that this workaround works fine:

if (SysStringLen(bstrFromCOMserver) > 0) {
    _bstr_t t(bstrFromCOMserver, false);    
    cout << t.length() << endl;
}

But I want to know why this don't work directly with _bstr_t or CComBSTR wrappers:

_bstr_t t(bstrFromCOMserver, false);
if (t.length() > 0) {...}

Update:

How COM server pass BSTR string:

void CALLBACK CProxy_ISTIQuoteEvents::OnSTIQuoteSnap(const structSTIQuoteSnap& structQuoteSnap) const { 
        if (SysStringLen(structQuoteSnap.bstrUpdateTime) > 0) {
            _bstr_t updateTime(structQuoteSnap.bstrUpdateTime, false);
        }
    }
}
Eldar Agalarov
  • 4,849
  • 4
  • 30
  • 38
  • Could you show how you call the COM server? E.g: `CComBSTR str; server->GetString(&str);` – noseratio Aug 11 '13 at 14:10
  • I added peace of code. BSTR string is field of struct which is passed by reference to event handler. – Eldar Agalarov Aug 11 '13 at 15:24
  • 1
    Sorry, I still don't get it. Is `OnSTIQuoteSnap` a method of your COM server? If so, how do you actually return the string? Anyway, this code looks wrong. Your `_bstr_t updateTime(structQuoteSnap.bstrUpdateTime, false)` is just an automatic stack variable. Because you specify `false` in its constructor, it takes over the passed BSTR string and frees its as soon as it goes out of its {} scope. Maybe this is the problem. – noseratio Aug 11 '13 at 15:39
  • COM server fire events and I use event sink clas, derived from IDispEventSimpleImpl. No, _bstr_t object is used in it's scope and then he become unnecessary. BUT I tried set second parameter to true in _bstr_t constructor and now it seems worked! Why? MSDN writes that if we set fCopy to true in the constructor then _bstr_t makes a copy of passed BSTR string using SysAllocString. But as I understand I don't need a copy of BSTR because passed BSTR string is already in the structure. – Eldar Agalarov Aug 11 '13 at 15:57
  • 1
    If `OnSTIQuoteSnap` is a method of your event sink, you should make a copy of this string. The caller (the server) keeps the ownership over `structQuoteSnap` structure and all its fields. By not making a copy of `bstrUpdateTime`, you 'steal' the ownership over the memory allocated for the string, and free this memory as soon as your local `_bstr_t` smart pointer variable goes out of scope. The server knows nothing about that and may continue using `bstrUpdateTime` and eventually try to free the same memory twice. – noseratio Aug 11 '13 at 16:23
  • 1
    Yes, OnSTIQuoteSnap is a method of my event sink. Thank You so much for your explanation! :) – Eldar Agalarov Aug 11 '13 at 16:27
  • No problem, hope that solved the problem. I posted it as the answer, so the question doesn't show up unanswered in the search. – noseratio Aug 12 '13 at 04:05

1 Answers1

1

The OnSTIQuoteSnap methods belongs to an event sink and is called back by the server, as we clarified in the comments. Thus, the server (as the caller) keeps the ownership over structQuoteSnap structure and all of its fields. updateTime is a local smart-pointer variable that should be making a copy of the string (structQuoteSnap.bstrUpdateTime), but it doesn't (as false is passed to its constructor), so it rather takes over the BSTR's memory. This memory is freed as soon as updateTime goes out of scope. The server knows nothing about that and may continue using bstrUpdateTime and may eventually try to free the same memory twice.

noseratio
  • 59,932
  • 34
  • 208
  • 486