¿Hay una manera más barata para encontrar la profundidad de la pila de llamadas que el uso de traza ()?

StackOverflow https://stackoverflow.com/questions/582673

  •  06-09-2019
  •  | 
  •  

Pregunta

Mi código de registro utiliza el valor de retorno de traza inversa () para determinar la corriente apilar profundidad (para la impresión bonitos), pero puedo ver desde perfilado que se trata de una llamada bastante caro.

No creo que hay una manera más barata de hacer esto? Tenga en cuenta que no se preocupan por las direcciones del bastidor, cuántos de ellos existen.

editar:. Estas funciones de registro se utilizan en todo una gran base de código, por lo que el seguimiento manualmente la profundidad de la pila no es realmente una opción

¿Fue útil?

Solución

El caminar de la pila a sí mismo es bastante rápido - la mayor parte de la lentitud en backtrace() es de buscar nombres de símbolos. En x86, puede hacer lo siguiente:

inline uint32_t get_ebp(void)
{
    __asm__ __volatile__("mov %%ebp, %%eax");
}

int get_stack_depth(void)
{
    uint32_t ebp = get_ebp();
    int stack_depth = 0;
    while(ebp != 0)
    {
        ebp = *(uint32_t *)ebp;
        stack_depth++;
    }
    return stack_depth;
}

Esto caminar por la cadena de punteros ebp. Tenga en cuenta que esto es extremadamente no portátil. También tenga en cuenta que esto no se hará válida cualquiera de las funciones que han sido inline o de llamada final optimizados (por supuesto, backtrace() tiene el mismo problema).

Otra cuestión importante es la condición de terminación - una vez que traza hasta main(), a menudo no son garantías acerca de lo que encontrará en la pila. Por lo tanto, si libc no pone un puntero trama nula, se le muy probable violación de segmento. Usted puede obtener el valor de terminación con mirarlo desde el principio de main().

Otros consejos

Si sus funciones de impresión legible están contenidas razonable, a continuación, pasar en el guión (guión o el tamaño) como un parámetro, y sólo se incrementa cuando se llama a otras funciones de visualización.

¿No puedes llevar un TLS variable de alrededor que se llama "profundidad "ay se incrementará / disminuirlo cada función? Mientras que usted puede escribir su propio código para caminar por la pila más rápido, todavía va a ser más lento que acaba de llevar a la variable con usted.

Para arquitecturas de brazo:

register unsigned long *rfp asm("fp");
unsigned long *fp = rfp;
unsigned long depth = 0;

while(fp)
{
    fp = (unsigned long *)(*(fp -3));
    depth++;
}

return depth;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top