У меня есть строка BSTR, которая передается с COM-сервера. Когда я помещаю эту строку в конструктор _bstr_t (или CComBSTR), происходит нарушение доступа. Я проверил это исключение и обнаружил, что это исключение возникает только тогда, когда BSTR пуст (или ноль).
Я пытался явно обнулять BSTR в конструкторе _bstr_t, и это прекрасно работает:
BSTR bstr = NULL;
_bstr_t t(bstr, false);
cout << t.length() << endl;
Но с BSTR, который передается с COM-сервера, это не работает — исключение нарушения доступа возникает, когда строка пуста или равна нулю (или может быть повреждена?)
Я обнаружил, что этот обходной путь работает нормально:
if (SysStringLen(bstrFromCOMserver) > 0) {
_bstr_t t(bstrFromCOMserver, false);
cout << t.length() << endl;
}
Но я хочу знать, почему это не работает напрямую с обертками _bstr_t или CComBSTR:
_bstr_t t(bstrFromCOMserver, false);
if (t.length() > 0) {...}
Обновить:
Как COM-сервер передает строку BSTR:
void CALLBACK CProxy_ISTIQuoteEvents::OnSTIQuoteSnap(const structSTIQuoteSnap& structQuoteSnap) const {
if (SysStringLen(structQuoteSnap.bstrUpdateTime) > 0) {
_bstr_t updateTime(structQuoteSnap.bstrUpdateTime, false);
}
}
}
OnSTIQuoteSnap
Методы принадлежат приемнику событий и вызываются сервером, как мы пояснили в комментариях. Таким образом, сервер (как вызывающий) сохраняет владение structQuoteSnap
структура и все ее поля. updateTime
является локальной переменной смарт-указателя, которая должна делать копию строки (structQuoteSnap.bstrUpdateTime
), но это не так (как false
передается его конструктору), так что он скорее забирает память BSTR. Эта память освобождается, как только updateTime
выходит за рамки. Сервер ничего не знает об этом и может продолжать использовать bstrUpdateTime
и может в конце концов попытаться освободить одну и ту же память дважды.
Других решений пока нет …