Вопрос

У меня есть следующий код:

std::string F()
{
  WideString ws = GetMyWideString();

  std::string ret;
  StringUtils::ConvertWideStringToUTF8(ws, ret);
  return ret;
}

WideString-это сторонний класс, как и StringUtils. Они для меня черная коробка. Второй параметр передается ссылкой.

Когда я прохожу отладчик линию return ret бросает неприятное всплывающее окно (Visual C ++), говоря, что куча может быть повреждена. При более тщательной копии возвращаемой строки в порядке, но удаление ret терпит неудачу. ret содержит правильное значение перед возвратом.

Что может сделать функция преобразования, чтобы вызвать это? Есть идеи для исправления?

Обновлять:

  • Сам проект - это DLL
  • StringUtils - это либера
  • Проект составлен против многопоточного CRT (не отладка, а не DLL)
  • Программа, кажется, работает нормально при запуске за пределами Visual Studio
Это было полезно?

Решение

  1. Если StringUtils была скомпилирована отдельно (например, с другой версией компилятора), у вас может быть конфликт в макете объекта.
  2. Если StringUtils находится в DLL, вы должны убедиться, что как ИТ, так и основная программа будут составлены для использования стандартной библиотеки в DLL. В противном случае каждый модуль (исполняемый файл и DLL) будет иметь свою кучу. Когда Stringutils пытается играть с данными в строке, которая была выделена из другой кучи, случаются плохие вещи.

Другие советы

Дизайнер StringUtils разработал очень плохой API. Ни один из шаблонных стандартных типов библиотеки не должен использоваться в публичном интерфейсе API. std::string взорвано в линии. Таким образом, если используемые вами компилятор и библиотеки не совсем то же самое компилятор и библиотеки, используемые исполнителем StringUtils, типы могут и, вероятно, будут разными. По сути, реализатор StringUtils Не удалось отделить интерфейс от реализации.

Иллюстрация проблемы. Предположим, вы используете MSVC 9.0 SP1 и я использую MSVC 8.0. На моем компиляторе реализация Std :: String может выглядеть так:

class string
{
// : :  stuff
private:
  int someInt_;
  char* someBuf_;
};

... но на вашем компиляторе это может выглядеть по -другому:

class string
{
// : :  stuff
private: 

  void* impl_;
};

Если я напишу библиотечную функцию:

void DoSomethingWithAString(std::string& str);

... и вы называете это, sizeof(string) в вашем коде будет отличаться от sizeof(string) в моем коде. Типы не одинаковы.

У вас действительно есть только 2 решения вашей проблемы:

1) [Предпочтительнее] Получить реализатора StringUtils, чтобы исправить его разбитый код.

2) Замените библиотеку, используемую вашим компилятором в соответствии с библиотекой, используемой реализователем Stringutil. Возможно, вы сможете выполнить это, используя тот же компилятор на том же уровне патчей, что и использовался реализатор, предполагая, что он не заменил реализацию стандартной библиотеки.

РЕДАКТИРОВАТЬ: 3) Третий вариант - прекратить использование StringUtils. Честно говоря, это, вероятно, то, что я сделаю.

Из того, какой маленький код вы показываете, я полагаю StringUtils::ConvertWideStringToUTF8() принимает std::string& как второй параметр. Учитывая это, я не вижу, как ваш код может вызвать коррупцию кучи.

Обратите внимание, однако, что связывание библиотек C ++ в целом работает только тогда, когда код был составлен с использованием того же компилятора и одних и тех же настройки компилятора.

Ваше использование StringUtils а также WideString Делает это так, как будто вы используете C ++ Builder. Вы пытаетесь смешать модуль C ++ Builder и визуальный модуль C ++? Если это так, то вы определенно увидите проблемы, которые вы описали.

Вы не можете передать визуальный C ++ std::string к функции C ++ Builder, потому что код застройщика C ++ будет предполагать, что параметр использует C ++ Builder std::string определение. Классы могут иметь разные поля, а общие поля могут быть в другом порядке.

Даже если классы имеют одинаковые определения, модули все равно будут использовать разные менеджеры по памяти. Функция COLLED выделяет память для нового содержимого строки, используя свой диспетчер памяти, и вызывающий абонент будет использовать свой собственный диспетчер памяти, чтобы попытаться освободить содержимое строки позже.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top