Нарушение прав доступа на CompStr (BSTR, BSTR) после получения строки?

Я получаю нарушение прав доступа, которое я не могу понять, пытаясь сравнить со строками BSTR в функции C ++. По какой-то причине большую часть времени код работает нормально. Но иногда, казалось бы, случайным образом, он генерирует исключение. Вот что я делаю:

BSTR myString; // also tried this with a CComBSTR, same result, but less often it seemed
pSomeObject->GetString(&myString);
if (!CompStr(someOtherString, myString))
{
  //do stuff
}

SomeObject :: GetString:

STDMETHODIMP SomeObject::GetString(BSTR* outStr)
{
  if (!outStr) return E_POINTER;

  *outStr = ::SysAllocString(m_memberString);

  return S_OK;
}

Я получаю нарушение прав доступа в CompStr:

inline bool CompStr(BSTR str1, BSTR str2)
{
  UINT len1 = ::SysStringLen(str1);
  UINT len2 = ::SysStringLen(str2);  // this is where I'm getting the access violation

  return CompStr(str1, len1, str2, len2);
}

Есть идеи о том, что я делаю неправильно или почему это не удается?


person climbak    schedule 11.09.2014    source источник
comment
Вы уверены, что и str1, и str2 были распределены с помощью SysAllocString?   -  person Ross Ridge    schedule 12.09.2014
comment
Я почти уверен, что это так. Я знаю, что моя строка (str2) инициализируется, но я углублюсь в другие пути кода, чтобы увидеть, не инициализируется ли где-то str1.   -  person climbak    schedule 12.09.2014
comment
В отладчике проверьте значение str2. Также ранее могло быть неопределенное поведение (например, переполнение буфера), и только когда вы выделяете другую строку, это повреждение проявляется.   -  person M.M    schedule 12.09.2014
comment
@climbak не просто где-то инициализирован, он должен быть специально создан с SysAllocString (или семейством). BSTR - строка с подсчетом длины; если вы попытаетесь передать строку с завершающим нулем (без подсчета длины), тогда у вас возникнут некоторые проблемы   -  person M.M    schedule 12.09.2014


Ответы (1)


Вы не инициализируете myString и не проверяете GetString() на наличие ошибки.

BSTR myString = NULL; // CComBSTR initializes for you
if (SUCCEEDED(pSomeObject->GetString(&myString)))
{
    if (!CompStr(someOtherString, myString))
    {
        //do stuff
    }
}

STDMETHODIMP SomeObject::GetString(BSTR* outStr)
{
    if (!outStr) return E_POINTER;

    *outStr = ::SysAllocString(m_memberString);
    if (!*outStr) return E_OUTOFMEMORY;

    return S_OK;
}

Also, make sure someOtherString is allocated as a BSTR, otherwise SysStringLen() will not work on it. I would suggest changing CompStr() to use WCHAR* and lstrlenW() instead. You can pass a BSTR to a WCHAR*:

inline bool CompStr(WCHAR* str1, WCHAR* str2)
{
    UINT len1 = ::lstrlenW(str1);
    UINT len2 = ::lstrlenW(str2);

    return CompStr(str1, len1, str2, len2);
}
person Remy Lebeau    schedule 11.09.2014
comment
К сожалению, я ограничен BSTR, но я посмотрю на someOtherString и посмотрю, есть ли у него пути в другом коде, где он не инициализируется. Спасибо за советы. - person climbak; 12.09.2014
comment
@climbak Вам не нужно инициализировать myString, поскольку вы установили GetString и не смогли проверить возвращаемое значение SysAllocString, это не приведет к сбою SysStringLen, потому что он возвращает 0, если передан нулевой указатель. Однако изменение кода для использования lstrlenW или wcslen стоит попробовать, чтобы увидеть, не приведет ли это к другому поведению вашего кода. - person Ross Ridge; 12.09.2014
comment
Если это, кажется, решает проблему, то OP, должно быть, неправильно выделил str1, поэтому это следует исправить, иначе проблема того же типа может просто проявиться в другом фрагменте кода. - person M.M; 12.09.2014
comment
Я получал строку из другой функции, которая получает ее из разных мест в зависимости от условий. Один из них не использовал SysAllocString и просто ничего не возвращал. - person climbak; 15.09.2014