2012-03-21 11 views
6

Me encuentro en la difícil situación de tener que depurar una aplicación Qt sin casi ninguna herramienta de depuración: la aplicación parece comenzar a usar más y más CPU ya que ejecuta la misma acción una y otra vez; después de muchas horas, la CPU está completamente saturada.Técnicas de depuración sin herramientas de depuración

La aplicación se ejecuta en un dispositivo ARM Linux incrustado donde gdb parece no funcionar, tal vez problemas difíciles de descubrir con la cadena de herramientas proporcionada. Parece que strace solo informa las actividades del temporizador (esta es una aplicación OpenGL así que esto se espera). ltrace no está disponible y compilarlo resultó en una tarea difícil, tal vez inútil. No escribí la aplicación, pero el código fuente está disponible.

¿Hay algo más que pueda hacer para descubrir qué hace la aplicación ocupada cuando consume tantos recursos? De cualquier forma, tengo que rastrear todas las llamadas a métodos que hace la aplicación? ¿Hay alguna otra técnica que pueda usar para tratar de adivinar el problema o dónde enfocar mi atención?

EDITAR: Este es uno de los problemas con gdb: Only question marks in backtrace reported by gdb on ARM. Incluso escribiendo una aplicación de diez líneas que simula una segfault resulta en esto.

+0

¿Has probado la depuración remota? – manasij7479

+0

puede ejecutar valgrind? – WeaselFox

+0

Depuración remota con gdb? Intenté durante horas sin éxito. valgrind también tiene problemas. Nadie fue capaz de hacer que estas herramientas funcionaran en esta plataforma. Considere también que las libs del sistema están desmanteladas. –

Respuesta

4

¿Se pueden habilitar los volcados del núcleo en la máquina? Luego, cuando se está reproduciendo, puede enviarle un SIGABRT y copiar el volcado del núcleo a su máquina de desarrollo, y examinarlo con un depurador cruzado, con el archivo fuente y el ejecutable no desensamblado disponibles.

También es importante aprender la lección amarga para la próxima vez, no use una cadena de herramientas tan mal soportada.

Si se trata de una opción, puede probar otra cadena de herramientas con al menos gdbserver si no es compatible con gdb. He estado muy contento con la cadena de herramientas CodeSourcery ARM Lite.

EDIT: BGF para su situación se presenta en dos sabores:

  • una cruz-BGF que se ejecuta en el host desarrollo
  • una GDB nativo que se ejecuta en su objetivo

gdbserver permite usted puede ejecutar cross-gdb en su host de desarrollo y conectarse al destino para depurar remotamente algo que se ejecuta en él. Por lo tanto, un volcado de núcleo o gdbserver son dos formas de usar un cross-gdb para inspeccionar algo en el objetivo, pero gdbserver por sí solo no te ayudará mucho.

Si su compilador cruzado es algo así como arm-none-linux-gnueabi-gcc, vea si tiene un arm-none-linux-gnueabi-gdb disponible en su host de desarrollo.

+0

¡Esto es muy interesante! Pero veo que necesito que gdb lea el vertedero. No creo que tenga gdb disponible para la plataforma, solo gdbserver para la depuración remota, que también parece no funcionar correctamente. ¿Puedo probar esto con esa herramienta? –

+0

¿Es este un dispositivo ARM muy inusual? De lo contrario, debería poder construir fácilmente gdb desde las fuentes. – dbrank0

+0

Este es un buen consejo. ¡Gracias! Este es un dispositivo con un Linux incorporado construido desde cero. –

0

Intente registrar el tiempo de ejecución de diferentes funciones. Primero, registre el tiempo de ejecución de los candidatos más probables y, si los ha eliminado, continúe con las otras funciones menos probables de su programa.

La forma más sencilla de registrar un mensaje es usar std :: cout (o printf) y redirigir el archivo a un archivo para que pueda verlo más tarde.

3

Puede intentar colocar algún código de depuración en su aplicación.

Elija alguna señal, como SIGINT. Agregue manejador de señal para esta señal. En este controlador, imprima la traza de pila o al menos el valor del puntero de instrucción. Luego, inicie la aplicación y envíe SIGINT varias veces para ver qué está haciendo su aplicación.

+0

Sí, ya lo he intentado. Pero al igual que gdb, parece que no puedo tener el nombre de las funciones en el backtrace, lo que hace que el backtrace sea inútil. backtrace_symbols parece no poder hacer coincidir el puntero con la cadena, incluso cuando los símbolos están en mi binario. –

+0

Siempre puede imprimir el puntero de instrucción. Y luego encuéntrelo en el archivo del mapa. –

+0

¡Probé esto en un código de muestra y parece funcionar al exportar símbolos con rdinámica! El problema ahora es que por alguna razón desconocida en la aplicación que estoy analizando no puedo detectar SIGINT. –

0

Puede intentar ejecutar la versión ARM del perfilador Zoom, esto le indicará dónde pasa la mayor parte del tiempo su código, puede descargarlo gratuitamente con una licencia de evaluación de 30 días.

0

Suponiendo que gcc tiene algo así como macros de línea y archivo MSVC, que se expanden hasta el archivo actual y la línea actual, puede hacer su propia función de pseudo-perfilado. Poner esto en un encabezado:

void MyPseudoProfileLog(const char* file, int line, int* count); 
#define MY_PSEUDO_PROFILE_LOG(file, line) { static int count = 0; MyPseudoProfileLog(file, line, &count); } 

Esto va en un archivo cpp (si lo pones en la cabecera obtendrá múltiples copias de la variable estática, una para cada archivo CPP que incluyen la cabecera):

void MyPseudoProfileLog(const char* file, int line, int* count) 
{ 
    static FILE* f = NULL; 
    const int max_count = 1000; 
    if (++(*count) == max_count) 
    { 
     *count = 0; 
     if (!f) 
      f = fopen("/tmp/my_pseudo_profile_log.log"); 
     fprintf(f, "file=\"%s\", line=%d was passed %d times\n", file, line, max_count); 
     fflush(f); 
    } 
} 

continuación, puede pegar

MY_PSEUDO_PROFILE_LOG(__FILE__, __LINE__); 

a varios lugares en el código para ver con qué frecuencia se denominan. Tenga en cuenta que esto no es seguro para subprocesos, así que use solo en el hilo principal.

+0

Colocar líneas de registro es lo que estoy haciendo sí, el problema es que hay cientos de llamadas a métodos en varias bibliotecas. Puede llevar semanas encontrar a los que cargan la CPU. –

Cuestiones relacionadas