microsoft - paquetes redistribuibles de visual c++ para visual studio 2013
¡Depuración de aserción! Expresión:_pFirstBlock== pHead (4)
Esto es lo que assert() cuando su argumento de expresión se evalúa como falso. Esta afirmación existe en la compilación Debug de la biblioteca C runtime, diseñada para verificar problemas de asignación. La función gratuita () en tu caso. La compilación Debug agrega comprobaciones adicionales para asegurarse de que está escribiendo su código correctamente. Y te digo cuando detecta un problema. Como llamar a free () en una asignación que ya fue liberada, el caso simple. O llamando a free () pasando el valor del puntero equivocado, el caso más complicado. O llamando a free () cuando el montón fue corrompido por un código anterior, el caso mucho más difícil.
Esto es solo lo que pueden tomar, no saben por qué su código se equivocó. No hay forma de que puedan poner una flecha grande roja en el código que corrompió el montón, por ejemplo. El caso fácil está cubierto por la ventana del depurador Debug + Windows + Call Stack, lo lleva al código en su programa que llamó a free (). O std::operator delete
para un programa C ++. El caso más difícil es muy, muy difícil, la corrupción del montón es a menudo un Heisenbug. Hacer que la afirmación sea repetible para que pueda establecer un punto de interrupción de datos en la dirección informada es la estrategia central. Cruzando los dedos para el caso fácil, ¡buena suerte con él!
Después de editar: sí, tener problemas de módulos cruzados con una clase de C ++ como std :: string es sin duda uno de los problemas que puede atrapar. No es un Heisenbug, es un buen tipo de problema. Dos problemas básicos con eso:
- Los módulos pueden tener cada uno su propia copia del CRT, los objetos asignados por una copia del CRT no pueden ser liberados por otra copia del CRT. Cada uno tiene su propio montón al que asignan. Un problema abordado en VS2012, el CRT ahora asigna desde un montón de procesos globales.
- Los módulos pueden no usar la misma implementación de std :: string. Con un diseño de objeto que no coincide. Fácilmente inducido por tener los módulos compilados con diferentes versiones de bibliotecas de C ++, particularmente un problema con los cambios de C ++ 11. O diferentes configuraciones, la macro _HAS_ITERATOR_DEBUGGING es bastante notoria.
La única solución para ese problema es asegurarse de que compila todos los módulos de su programa con la misma versión de compilación utilizando la misma configuración de compilación. Usar / MD es obligatorio, asegura que el CRT se comparte, por lo que solo hay uno en el programa.
Llamo a un .dll enlazado estáticamente, y veo este error:
Escribí el .dll y el código de llamada. Este error no debería estar ocurriendo. Me pregunto si alguien más lo ha visto antes. El .dll solo contiene unas 10 líneas de código, es solo un .dll de prueba para ver cómo funcionan los dlls en general. Se explota cuando paso una cadena std :: fuera del .dll.
Estoy usando Visual Studio 2012 y C ++.
Lo que intentaré a continuación
De la afirmación de Debug ... _pFirstBlock == pHead :
Este problema puede ocurrir si uno usa las bibliotecas de subprocesamiento único en un módulo multiproceso.
Mañana, intentaré recompilar las bibliotecas estáticas de Boost en modo de subprocesos múltiples (mi .dll está configurado en modo estático de subprocesos múltiples).
Lo que intentaré a continuación
Consulte Uso de cadenas en un objeto exportado desde una DLL que causa un error de tiempo de ejecución :
Tienes que hacer una de dos cosas
- Haga que tanto el DLL como el cliente que lo utilizan tengan un enlace a la versión DLL del CRT (p. Ej., No de forma estática).
- O bien, debe asegurarse de no pasar memoria asignada dinámicamente (como la contenida en objetos de cadena) a través de los límites de la DLL. En otras palabras, no tiene funciones exportadas por DLL que devuelvan objetos de cadena.
Joe
Esto parece coincidir con lo que está sucediendo, explota en el punto preciso en el que paso una secuencia de regreso a través de un límite .dll. El problema solo ocurre cuando todo está vinculado en modo estático. Ahora eso es reparable.
Consulte Pase de referencia al vector STL sobre el límite dll .
Lo que intentaré a continuación
Consulte Imposible pasar std :: wstring en DLL .
Solución
Tengo una buena solución, mira la respuesta a continuación.
La causa probable: enlace a la versión incorrecta de las DLL de Qt, especialmente al mover un proyecto de VS2010 a VS2012.
Esto se debe a diferentes versiones de la biblioteca estándar y problemas asociados de asignación dinámica.
Tuve el mismo problema después de una reinstalación de Windows. La compilación de mi biblioteca de Runtime era DLL de depuración de varios subprocesos ( /MDd
).
Mi solución fue eliminar el archivo *.user
del proyecto de Visual Studio, eliminar la carpeta de depuración y reconstruir el proyecto.
En este caso, el problema es que estaba pasando una std::string
a través de un límite .dll.
Configuración de la biblioteca Runtime
Si la
Runtime library
MSVCRuntime library
está configurada enMulti-threaded Debug DLL (/MDd)
, entonces esto no es un problema (funciona bien).Si la
Runtime library
MSVCRuntime library
está configurada enMulti-threaded Debug (/MTd)
, arrojará este error, que se puede corregir con las siguientes instrucciones.
Memoria asignada en el Administrador de memoria A y liberada en el Administrador de memoria B ...
El problema es que la memoria se asigna en el lado .dll, luego esa misma memoria se libera en el lado de la aplicación. Esto significa que el administrador de memoria A está asignando memoria, y el administrador de memoria B está liberando esa misma memoria, lo que genera errores.
La solución es asegurarse de que toda la memoria devuelta no esté asignada en el archivo DLL. En otras palabras, la memoria siempre se asigna en el lado de la aplicación y se libera en el lado de la aplicación.
Por supuesto, la DLL puede asignar / liberar memoria internamente, pero no puede asignar memoria que luego libera la aplicación.
Ejemplos
Esto no funcionará:
// Memory is allocated on the .dll side, and freed on the app side, which throws error.
DLL std::string GetString();
Esto funcionará:
// Memory is allocated/freed on the application side, and never allocated in the .dll.
DLL int GetString(std::string& text);
Sin embargo, esto no es suficiente.
En el lado de la aplicación, la cadena debe ser preasignada:
std::string text("");
text.reserve(1024); // Reserves 1024 bytes in the string "text".
En el lado .dll, el texto debe copiarse en el búfer original (en lugar de sobrescribirse con la memoria asignada en el lado .dll):
text.assign("hello");
A veces, C ++ insistirá en asignar memoria de todos modos. Verifique que la preasignación sigue siendo la misma que era:
if (text.capacity < 1024)
{
cout << "Memory was allocated on the .dll side. This will eventually throw an error.";
}
Otra forma de hacerlo es usar std::shared_ptr<std::string>
, por lo que, aunque la memoria esté asignada en .dll, es liberada por el .dll (en lugar del lado de la aplicación).
Otra forma es aceptar un char *
y una longitud que indique la cantidad de memoria preasignada. Si el texto que queremos devolver es más largo que la longitud de la memoria preasignada, devuelve un error.