Frage

Mein Logging-Code verwendet den Rückgabewert von Backtrace () den Strom zu bestimmen, Stack-Tiefe (für ziemlich Druckzwecke), aber ich kann sehen, aus Profilierungs, dass dies ein ziemlich teuer Anruf ist.

Ich glaube nicht, gibt es einen billigeren Weg, dies zu tun? Beachten Sie, dass ich nicht über die Rahmenadressen egal, wie viele von ihnen gibt.

bearbeiten. Diese Anmeldung all Funktionen über eine große Code-Basis verwendet, so manuell die Stapeltiefe Tracking nicht wirklich eine Option ist

War es hilfreich?

Lösung

Gehen der Stapel selbst ziemlich schnell ist - die meisten der Langsamkeit in backtrace() von aufzublicken Symbolnamen ist. Auf x86, können Sie Folgendes tun:

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

Damit wird die Kette von ebp Zeiger gehen. Beachten Sie, dass diese extrem nicht tragbar ist. Beachten Sie auch, dass dies keine Funktionen zählen, die inlined oder Tail-Call optimiert wurden (natürlich backtrace() hat das gleiche Problem).

Ein weiteres wichtiges Thema ist die Abbruchbedingung - sobald Sie main() Backtrace bis zu, gibt es oft keine Garantie darüber, was Sie in dem Stapel finden. Also, wenn libc kein Null-Frame-Zeiger nicht setzen, werden Sie sehr wahrscheinlich segfault. Sie können ganz am Anfang von main() an den Beendigungswert erhalten, indem suchen.

Andere Tipps

Wenn Ihr recht-Druckfunktionen vernünftigerweise enthalten sind, dann in dem Gedankenstrich passieren (oder Einrückungsgröße) als Parameter, und es nur erhöht werden, wenn Sie eine andere Anzeigefunktionen aufrufen.

Sie können nicht tragen nur einen TLS Variable um mit Ihnen „Tiefe genannt "und erhöht es / oder vermindern, jede Funktion? Während Sie Ihren eigenen Code schreiben konnten den Stapel schneller zu gehen, geht es noch langsamer sein als nur mit der Sie die Variable um tragen.

Für ARM-Architekturen:

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

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

return depth;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top