Actualmente estoy trabajando en un sistema de informe de errores basado en excepciones para aplicaciones Windows MSVC++ (9.0) (es decir, estructuras de excepción & tipos/herencia, pila de llamadas, registro de errores &, etc.).
Mi pregunta ahora es: ¿cómo informar correctamente & registrar un error de memoria?
Cuando se produce este error, p. como bad_alloc
lanzada por el new
op, puede haber muchas "características" no disponibles, principalmente relacionadas con la asignación de memoria adicional. Normalmente, apruebo la excepción a la aplicación si se ha lanzado en una lib y luego uso los cuadros de mensaje y los archivos de registro de errores para informar y registrarla. Otra forma (principalmente para los servicios) es usar el registro de eventos de Windows.
El principal problema que tengo es armar un mensaje de error. Para proporcionar cierta información de error, me gustaría definir un mensaje de error estático (puede ser una cadena literal, mejor una entrada en un archivo de mensaje, luego usar FormatMessage) e incluir alguna información en tiempo de ejecución como una pila de llamadas.
Las funciones/métodos necesarios para este uso ya seaC++/Windows: cómo informar una excepción de falta de memoria (bad_alloc)?
- STL (
std::string, std::stringstream, std::ofstream
) - CRT (
swprintf_s, fwrite
) - o Win32 API (
StackWalk64, MessageBox, FormatMessage, ReportEvent, WriteFile
)
Además de ser documentada en la MSDN, todos ellos más (Win32) o menos (STL) de fuente cerrada en Windows, por lo que no sé realmente cómo se comportan en problemas de poca memoria.
Sólo para demostrar que puede haber problemas, escribí una pequeña aplicación trivial provocando una bad_alloc:
int main()
{
InitErrorReporter();
try
{
for(int i = 0; i < 0xFFFFFFFF; i++)
{
for(int j = 0; j < 0xFFFFFFFF; j++)
{
char* p = new char;
}
}
}catch(bad_alloc& e_b)
{
ReportError(e_b);
}
DeinitErrorReporter();
return 0;
}
Ran dos instancias w/o depurador asociado (en la configuración de lanzamiento, VS 2008), pero "no pasó nada ", es decir, no hay códigos de error de ReportEvent o WriteFile que utilicé internamente en el informe de errores. Luego, lanzó una instancia con y sin depurador y les permitió tratar de informar sus errores uno tras otro utilizando un punto de interrupción en la línea ReportError. Eso funcionó bien para la instancia con el depurador conectado (informó correctamente & registró el error, incluso utilizando LocalAlloc sin problemas)! Pero el taskman mostró un comportamiento extraño, donde hay mucha memoria liberada antes de que la aplicación salga, supongo que cuando se lanza la excepción.
Por favor, considere que puede haber más de un proceso [editar] y más de un hilo [/ editar] consumir mucha memoria, así liberando espacio de montón pre-asignado no es una solución segura para evitar un entorno de memoria baja para el proceso que quiere reportar el error.
Gracias de antemano!
¿Ha considerado tener un bloque de memoria reservado de antemano que se convertirá en la fuente de colocación asignaciones cada vez que el sistema entra en una situación de falta de memoria? Solo he usado este método para salir con gracia de la aplicación, pero los sistemas operativos (OpenSolaris, Linux) hacen algo similar para dar a la aplicación el tiempo suficiente para liberar o intercambiar asignaciones de baja prioridad y recuperar con gracia. – Sniggerfardimungus
Actualmente, Uso un poco de espacio en la pila (las variables miembro declaradas al llamar a InitErrorReporter) para proporcionar búferes a las funciones CRT/WinSDK. Pero no sé lo que hacen internamente: ver el informe de Alex Farber. – dyp
http://stackoverflow.com/questions/1308052/policy-with-catching-stdbad-alloc hablar sobre algo similar – Chubsdad