bds 2006 C conflictos de administrador de memoria oculta (clase nueva / eliminar vs. AnsiString)

Estoy usando BDS 2006 Turbo C ++ durante mucho tiempo y algunos de mis proyectos más grandes ( CAD / CAM, motores gfx 3D y cálculos Astronomic) ocasionalmente lanzan una excepción (por ejemplo, una vez en 3-12 meses de uso intensivo las 24 horas, los 7 días de la semana) ) Después de una depuración exhaustiva, encontré esto:

//code1: struct _s { int i; } // any struct _s *s=new _s[1024]; // dynamic allocation delete[] s; // free up memory 

este código generalmente está dentro de la plantilla donde _s también puede ser de clase, por lo tanto, delete[] este código debería funcionar correctamente, pero la delete[] no funciona correctamente para las estructuras (las clases se ven bien). No se lanzan excepciones, la memoria se libera, pero de alguna manera daña las tablas de asignación del administrador de memoria y después cualquier asignación nueva puede ser incorrecta (la nueva puede crear asignaciones superpuestas con espacio asignado o incluso espacio no asignado, por lo tanto, las excepciones ocasionales)

He encontrado que si agrego el destructor vacío a _s de repente todo parece estar bien

 struct _s { int i; ~_s(){}; } 

Bueno, ahora viene la parte extraña. Después de actualizar esto a mis proyectos, he encontrado que la clase AnsiString también tiene malas reasignaciones. Por ejemplo:

 //code2: int i; _s *dat=new _s[1024]; AnsiString txt=""; // setting of dat for (i=0;i<1024;i++) txt+="bla bla bla\r\n"; // usage of dat delete[] dat; 

En este código, dat contiene algunos datos útiles, luego aparece una cadena de texto creada agregando líneas, por lo que el texto debe ser reasignado pocas veces y, a veces, los datos dat son sobrescritos por txt (incluso si no están superpuestos, creo que la temperatura necesaria es AnsiString para reasignar txt se superpone con dat )

Entonces mis preguntas son:

  1. ¿Estoy haciendo algo mal en code1, code2?
  2. ¿Hay alguna manera de evitar los AnsiString (re) allocation? (pero aún usándolo)

    • Después de una depuración exhaustiva (después de publicar la pregunta 2), he descubierto que AnsiString no causa problemas. Solo ocurren mientras los usan. El verdadero problema probablemente sea al cambiar de cliente OpenGL . Tengo diálogos de Abrir / Guardar con vista previa para gráficos vectoriales. Si desactivo el uso de OpenGL para estas AnsiString de AnsiString memoria de AnsiString desaparece por completo. No estoy seguro de cuál es el problema (la incompatibilidad entre las ventanas de MFC / VCL o más bien cometí un error al cambiar de contexto, investigaré más a fondo). Las ventanas OpenGL con preocupación son:
    • Formulario principal de VCL + OpenGL dentro del área del cliente de Canvas
    • hijo del diálogo principal Abrir / Guardar de MFC + vista previa acoplada Formulario VCL + OpenGL dentro del área del cliente de Canvas

PD

  1. estos errores dependen del número de usos new/delete/delete[] no en los tamaños asignados
  2. los errores de code1 y code2 son repetitivos (por ejemplo, tienen un analizador para cargar archivos ini complejos y el error ocurre en la misma línea si no se cambia la ini)
  3. Detecto estos errores solo en grandes proyectos (código fuente simple> 1MB) con el uso combinado de AnsiString y plantillas con asignaciones dinámicas internas, pero es posible que también estén en proyectos más simples, pero ocurre tan raramente que lo extraño.
  4. Especificaciones de proyectos infectados:
    • win32 noinstall independiente (con Win7sp1 x64 pero en XPsp3 x32 se comporta de la misma manera)
    • no mide si usa GDI o OpenGl / GLSL
    • no mide si usa DLL de controlador de dispositivo o no
    • no OCX , o componente VCL no estándar
    • sin DirectX
    • Comstackción / enlace alineado por 1 byte
    • no use RTL , paquetes o marcos (independiente)

Perdón por mal inglés / gramática … cualquier ayuda / conclusión / sugerencia apreciada.

Después de una depuración exhaustiva, finalmente aislé el problema. La administración de memoria de bds2006 Turbo C ++ se corrompió después de intentar llamar a cualquier eliminación del puntero ya eliminado. por ejemplo:

 BYTE *dat=new BYTE[10],*tmp=dat; delete[] dat; delete[] tmp; 

Después de esto, la administración de la memoria no es confiable. (‘nuevo’ puede asignar espacio ya asignado)

Por supuesto, la eliminación del mismo puntero dos veces es un error en el lado de los progtwigdores, pero he encontrado la verdadera causa de todos mis problemas que generan este problema (sin ningún error obvio en el código fuente) vea este código:

 //--------------------------------------------------------------------------- class test { public: int siz; BYTE *dat; test() { siz=10; dat=new BYTE[siz]; } ~test() { delete[] dat; // <- add breakpoint here siz=0; dat=NULL; } test& operator = (const test& x) { int i; for (i=0;i 

En la función get() se llama destructor para la clase a dos veces. Una vez para real ay una para su copia porque se me olvida crear el constructor

 test::test(test &x); 

[Editar1] más actualizaciones del código

OK He refinado el código de inicialización para las plantillas even y struct even para arreglar aún más bug-cases. Agregue este código a cualquier estructura / clase / plantilla y, si es necesario, agregue la funcionalidad

 T() {} T(T& a) { *this=a; } ~T() {} T* operator = (const T *a) { *this=*a; return this; } //T* operator = (const T &a) { ...copy... return this; } 
  • T es el nombre de la estructura / clase
  • el último operador es necesario solo si T usa asignaciones dinámicas dentro de él si no se utilizan asignaciones, puede dejarlo como está

Esto también resuelve otros problemas del comstackdor como este:

  • Demasiados errores de inicializadores para una matriz simple en bcc32

Si alguien tiene problemas similares, espero que esto ayude.

También mire en traceback un puntero en código c ++ mmap si necesita depurar sus asignaciones de memoria ...

Intereting Posts