Маршалинг BSTRs от C++ до C# со взаимодействующим с COM

Да, == плохо для сравнения Строк (любые объекты действительно, если Вы не знаете, что они являются каноническими). == просто сравнивает ссылки на объект. .equals() тесты для равенства. Для Строк часто они будут тем же, но поскольку Вы обнаружили, это всегда не гарантируется.

6
задан Andy Johnson 19 August 2009 в 14:38
поделиться

3 ответа

Анельсон рассмотрел это довольно хорошо, но я хотел добавить пару моментов;

  • CoTaskMemAlloc - не единственный COM-дружественный распределитель - BSTR распознаются маршаллером по умолчанию, и будет освобожден / перераспределен с помощью SysAllocString и друзей.

  • Во избежание USES_CONVERSION (из-за риска переполнения стека - см. ответ Анельсона) ваш полный код должен быть примерно таким [1]

(обратите внимание, что A2BSTR безопасен использовать, поскольку он вызывает SysAllocString после преобразования и не использует динамическое выделение стека. Кроме того, используйте удаление массива (delete []), поскольку BuildResponse, вероятно, выделяет массив символов)

  • Распределитель BSTR имеет кеш, который может создать впечатление утечки памяти. См. http://support.microsoft.com/kb/139071 для получения дополнительной информации или Google для OANOCACHE. Вы можете попробовать отключить кеш и посмотреть, исчезнет ли «утечка».

[1]

HRESULT MyClass::ProcessRequest(BSTR request, BSTR* pResponse)
{
    char* pszResponse = BuildResponse(CW2A(request));
    *pResponse = A2BSTR(pszResponse);
    delete[] pszResponse;
    return S_OK;
}
2
ответ дан 17 December 2019 в 22:14
поделиться

Я не вижу очевидная проблема с вашим кодом. Предлагаем вам изменить метод ProcessRequest, чтобы исключить COM-взаимодействие как источник утечки:

HRESULT MyClass::ProcessRequest(BSTR request, BSTR* pResponse)
{
    *psResponse = ::SysAllocStringLen(L"[suitably long string here]");
    return S_OK;
}

Я подозреваю, что утечки не будет, и в этом случае вы сузили утечку до своего кода.

Я также хотел бы отметить OLE2A выделяет память в стеке, поэтому вы не только не должны удалять pszRequest, но и вообще не должны использовать OLE2A из-за возможности переполнения стека. См. эту статью для более безопасных альтернатив.

Я также предлагаю вам заменить A2BSTR на :: SysAllocString (CA2W (pszResponse))

3
ответ дан 17 December 2019 в 22:14
поделиться

Думаю, вам нужно уничтожить запрос с помощью :: SysFreeString () . Эта память выделяется на стороне сервера.

Кроме того, OLE2A может выделять память из-за преобразования (посмотрите). Вы также не освобождаете его.

-4
ответ дан 17 December 2019 в 22:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: