Pregunta

Tengo el siguiente código:

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

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

WideString es una clase de terceros, por lo que son StringUtils. Se trata de una caja negra para mí. El segundo parámetro se pasa por referencia.

Cuando me paso a través del depurador del return ret línea lanza una ventana emergente desagradable (Visual C ++) diciendo que el montón puede estar dañado. Una vez más cerca copia examen de la cadena que es retornada está bien, pero la eliminación de ret falla. ret contiene valor correcto antes de vuelta.

Lo que podría convertir la función de hacer posiblemente para causar esto? Cualquier idea fijar?

Actualización:

  • Proyecto en sí es una DLL
  • StringUtils es un lib
  • Proyecto se compila contra multiproceso CRT (no de depuración, no DLL)
  • Programa parece funcionar bien cuando se ejecuta fuera de Visual Studio
¿Fue útil?

Solución

  1. Si StringUtils fue compilado por separado (por ejemplo, con una versión del compilador diferente), que puede tener un conflicto en el diseño de objetos.
  2. Si es StringUtils en un DLL, usted tiene que asegurarse de que tanto él como el programa principal se compilan a utilizar la biblioteca estándar en un archivo DLL. De lo contrario, cada módulo (ejecutables y DLL) tendrá su propia pila. Cuando StringUtils trata de jugar con los datos de la cadena que se asigna a partir de una pila diferente, suceden cosas malas.

Otros consejos

El diseñador de StringUtils diseñado una API muy pobre. Ninguno de los tipos de biblioteca estándar de plantilla se debe utilizar en la interfaz pública de la API. std::string es soplado hacia fuera en línea. Así que si el compilador y bibliotecas que está utilizando no es exactamente el mismo compilador y bibliotecas utilizado por el implementador de StringUtils, los tipos pueden y probablemente será diferente. Fundamentalmente, el implementador de StringUtils para separar la interfaz de la aplicación.

Una ilustración del problema. Supongamos que usted está utilizando MSVC 9.0 SP1 y estoy usando MSVC 8.0. En mi compilador, la implementación de std :: string podría tener este aspecto:

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

... pero en su compilador podría tener un aspecto diferente:

class string
{
// : :  stuff
private: 

  void* impl_;
};

Si escribo una función de biblioteca:

void DoSomethingWithAString(std::string& str);

... y usted lo llama, el sizeof(string) en su código será diferente que el sizeof(string) en mi código. Los tipos no son lo mismo.

en realidad sólo tienen 2 soluciones a su problema:

1) [preferido] Obtener el implementador de StringUtils de fijar su código roto.

2) Sustituir la biblioteca utilizada por el compilador para que coincida con la biblioteca utilizada por implementador de StringUtil. Usted puede ser capaz de lograr esto mediante el uso de la misma compilador al mismo nivel de parche que el implementador utilizado, suponiendo que no sustituyó la implementación de la biblioteca estándar.

EDIT: 3) Una tercera opción sería la de dejar de usar StringUtils. Sinceramente esto es probablemente lo que haría.

Por lo poco código que muestran, supongo StringUtils::ConvertWideStringToUTF8() toma una std::string& como segundo parámetro. Teniendo en cuenta que, no veo cómo su código puede causar daños en el montón.

Tenga en cuenta, sin embargo, que la vinculación de bibliotecas de C ++, en general, sólo funciona cuando alls el código fue compilado usando el mismo compilador y la misma configuración del compilador.

La utilización del StringUtils y WideString hace que parezca que estás usando C ++ Builder. ¿Estás tratando de mezclar un módulo C ++ Builder y un módulo de Visual C ++? Si es así, entonces definitivamente vería los problemas que has descrito.

No se puede pasar un std::string de Visual C ++ a una función de C ++ Builder porque el código C ++ Builder asumirá que el parámetro utiliza definición std::string de C ++ Builder. Las clases pueden tener diferentes campos, y los campos que tienen en común podría ser en un orden diferente.

Aunque las clases tienen las mismas definiciones, los módulos se siguen utilizando diferentes administradores de memoria. La función llamada asignará memoria para los nuevos contenidos de la cadena utilizando el gestor de memoria, y la persona que llama utilizará su propio gestor de memoria para intentar liberar el contenido de la cadena posterior.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top