C'è un modo più economico per trovare la profondità dello stack di chiamate che usare backtrace ()?

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

  •  06-09-2019
  •  | 
  •  

Domanda

Il mio codice di registrazione utilizza il valore di ritorno di backtrace () per determinare la corrente impilare profondità (per la stampa belle), ma posso vedere per profilatura che si tratta di una chiamata piuttosto costoso.

Non credo che ci sia un modo più economico di fare questo? Si noti che non mi interessa circa gli indirizzi del telaio, proprio come molti di loro non ci sono.

modifica:. Queste funzioni di registrazione sono utilizzati in tutto una grande base di codice, di tracking in modo manualmente la profondità dello stack non è realmente un'opzione

È stato utile?

Soluzione

A piedi la pila da soli è abbastanza veloce - la maggior parte della lentezza nel backtrace() da cercare i nomi dei simboli. Su x86, è possibile effettuare le seguenti operazioni:

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;
}

Questa camminerà la catena di puntatori ebp. Tenete a mente che questo è estremamente non portabile. Si noti inoltre che questo non conterà le funzioni che sono stati inlined o coda chiamata ottimizzati (ovviamente, backtrace() ha lo stesso problema).

Un altro aspetto importante è la condizione di terminazione - una volta che si backtrace fino a main(), lì spesso non sono garanzie su ciò che troverete nella pila. Quindi, se libc non mette a forma di cornice nullo, avrete molto probabilmente segmentation fault. È possibile ottenere il valore di terminazione, cercando in essa proprio all'inizio di main().

Altri suggerimenti

Se le funzioni pretty-stampa sono ragionevolmente contenuti, poi passano al trattino (o dimensione trattino) come parametro, e proprio incrementano quando si chiama altre funzioni del display.

Non puoi solo portare un href="http://en.wikipedia.org/wiki/Thread-local_storage" rel="nofollow noreferrer"> TLS variabile

Per le architetture braccio:

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

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

return depth;
scroll top