2010-03-18 21 views
19

Me pregunto si hay una buena manera de encontrar el código fuente que causa un error de corrupción del montón, dada la dirección de memoria de los datos escritos 'fuera' del montón asignado bloquear en Visual Studio;Visual Studio - cómo encontrar el origen de los errores de corrupción del montón

Dedicado elemento (0008) lista libre es 26F7F670 tamaño incorrecto (muertos)

(Tratando de escribir algunas notas sobre cómo encontrar los errores de memoria)

Gracias de antemano!

Respuesta

1

Puede establecer un punto de interrupción en una escritura en la dirección de memoria. El depurador le mostrará el código que escribe en la ubicación, pero aún necesita averiguar cuál de las escrituras está causando el problema.

0

Supongo que C++ es el idioma.

Si el error es reproducible y la dirección dañada es siempre la misma, puede poner un punto de interrupción de datos para detener el programa al escribir en esta dirección.

+1

El idioma es C/C++ mixto. La dirección dañada es diferente en cada sesión de depuración, así que supongo que no es posible utilizar un punto de interrupción de datos. – Danne

+1

Desafortunadamente, tienes razón. En estos casos, mi enfoque es #define libre/eliminar para que no sea nada. Si el problema desaparece, defino malloc/new/free/delete en una función que registra cada llamada, para encontrar eliminaciones o eliminaciones duplicadas sin una asignación. – Timores

3

Quizás puedas probar el Verificador de aplicaciones de Microsoft. Me solucionó un problema similar una vez, activando comprobaciones adicionales en las operaciones de montón. En mi opinión, la aleatoriedad de la dirección dañada se debe a que el montón se puede dañar "sutilmente", y el problema no se mostrará hasta que pase algo grande al montón (como asignación masiva/gratis).

36

Comienza con la instalación de windbg:

http://www.microsoft.com/whdc/Devtools/Debugging/default.mspx

después enciende la pageheap como esto:

gflags.exe –p /enable yourexecutable.exe /full 

Esto insertará una página que no se puede escribir después de cada asignación de montón.

Después de esto inicia el ejecutable desde dentro de windbg, cualquier escritura fuera del montón ahora será capturada por este depurador. Para activar la pageheap después utilizar esto:

gflags.exe -p /disable yourexecutable.exe 

Más información sobre cómo utilizar el pageheap here.

+3

¡La mejor solución! Salvó mi vida. Además, abrir gflags.exe directamente y usar la GUI también funciona. Vaya a "Archivo de imagen", complete el nombre del archivo ejecutable y marque "Activar montón de página". Cualquier depurador funcionará. – Eliko

+1

Muchas gracias. Me tomó dos días antes de descubrir esta técnica. Acabo de marcar "Habilitar el montón de páginas" y usar el depurador de Visual Studio como normalmente. Y luego, se romperá exactamente en la posición del código causando el error de corrupción del montón. Mi error se debe a que un hilo está alimentando continuamente los datos, mientras que otros hilos asignan solo la memoria suficiente para los datos antiguos, lo que no es suficiente para almacenar datos nuevos. – khanhhh89

+0

Estoy intentando instalar estas herramientas de depuración, pero me está pidiendo que desinstale el último SDK. Sugiera –

2

Probablemente sea demasiado tarde, pero si se compila con gcc y puede ejecutarse en Linux, puede usar valgrind para encontrar el origen del problema (no recuerdo las banderas, solo lo usé una vez con gran éxito).

+0

Buena suerte con eso, Microsoft ha hecho todo lo posible para asegurarse de que sus comandos de procesamiento de cadenas sean incompatibles con todos los estándares que puedan. Si es muy simple, puedes salirte con la tuya. – Owl

2

para la ventana 10 que podría permitir a la PageHeap option in the GFlags Tool, esta herramienta se incluye como parte de la Debugging Tools for Windows.

Las opciones de Heap de página en GFlags le permiten seleccionar la verificación de montón estándar o la verificación de montón de página completa. Tenga cuidado, la verificación completa del montón utiliza una página completa de memoria para cada asignación, por lo que puede causar falta de memoria en el sistema.

Para activar la pila de página en GFlags:

• Para habilitar estándar de pila de página de verificación, la versión estándar va a escribir un patrón al final de cada asignación del montón y luego examinar el patrón cuando las asignaciones son liberados .

Para verificar todos los procesos utilizan:

gflags/r + hpa

gflags/k + hpa

para un solo uso proceso:

gflags/p/habilitar ImageFileName

• Para habilitar completa la verificación de pila de página para un proceso, esta opción coloca una página inaccesible al final de cada asignación para que el programa se detiene inmediatamente si se trata de accesos memoria más allá de la asignación, esto solo debe usarse en un único proceso debido al gran consumo de memoria.

gflags/i ImageFileName + hpa

gflags/p/activar ImageFileName/full

Los dos comandos anteriores son intercambiables.

Nota: Todas las configuraciones de montón de página mencionadas anteriormente son configuraciones de todo el sistema almacenadas en el registro (excepto/k) y permanecerán vigentes hasta que las modifique. La configuración/k es una configuración de indicador Kernel establecida para esta sesión y se perderá cuando Windows se apaga

Otra herramienta útil es Application Verifier, pero esto no forma parte de las herramientas de depuración para Windows, sino que está incluido en el Windows Software Development Kit (SDK).

0

Asegúrese de que todas las bibliotecas a las que está enlazando están compiladas en la misma versión de CLR que la aplicación que está ejecutando, todas en Release o todas en Debug.

Cuando compila en depuración y versión, en realidad se está orientando a dos versiones diferentes de la biblioteca en tiempo de ejecución de C. Estas versiones son bastante diferentes y utilizan diferentes estrategias para asignar memoria y usan diferentes montones. Pero lo más importante es saber que NO son compatibles entre sí. La biblioteca de tiempo de ejecución Release C asignó la memoria como se esperaba, mientras que Depuración agregará información adicional, como bloques de protección para rastrear desbordamiento de búfer y la ubicación que llamó a la función de asignación, y a su vez asigna más memoria que Release.

Si está vinculando su aplicación a una combinación de DLL que se crearon en Release y Debug, lo más probable es que termine tratando de eliminar un objeto en un CLR que se creó en otro. Esto significa que intentará liberar más o menos memoria que la que se asignó al objeto y esto puede dañar el montón.

Debe compilar su aplicación, así como adjuntarla a las bibliotecas que están compiladas bajo la misma configuración, ya sea Release o Debug.

Este problema puede ocurrir especialmente en los módulos que se compilan con compiladores diferentes.

Hay una manera de evitar el problema, que mencionaré pero no recomiendo. Si por alguna razón aún necesita construir en diferentes modos, esta solución permitirá que toda la memoria se asigne y libere desde el mismo montón compartido. La API GetProcessHeap le permitirá acceder al montón compartido en los diferentes módulos. Al usar HeapAlloc & HeapFree, puede asignar y liberar memoria en el montón compartido. Nota: HeapAlloc y HeapFree deben reemplazar todas las llamadas a malloc y gratis en su aplicación.

+0

Compilo contra la misma versión de una biblioteca de terceros (por ejemplo OpenCV) en mi Debug and Release. Por lo que puedo decir, esto solo significa que, en la depuración, no puedo entrar en ninguno de los códigos de la parte 3d y que también se ejecuta un poco más rápido en la depuración. ¿Estoy equivocado, crees? –

+0

@ILIABROUDNO Por lo general, las bibliotecas de terceros que se distribuyen distribuirán una biblioteca de versiones que otros pueden usar en modo de liberación o depuración. Lo hacen al compilar sus archivos DLL para que incluyan su copia de la biblioteca de tiempo de ejecución de C, y se aseguran de que no compartan recursos de CRT como el montón a través de los límites de la biblioteca para garantizar que la memoria asignada dinámicamente se elimine en el mismo lado del límite. En conclusión, si las bibliotecas de terceros a las que está enlazando lo han hecho, no debería tener problemas para usarlas en Release así como en Debug. –

+0

@ILIABROUDNO si esto fue útil, por favor +1 :) –

Cuestiones relacionadas