Есть ли более дешевый способ определения глубины стека вызовов, чем использование backtrace ()? - PullRequest
0 голосов
/ 24 февраля 2009

Мой код регистрации использует возвращаемое значение backtrace () для определения текущей глубины стека (для красивых целей печати), но из профилирования видно, что это довольно дорогой вызов.

Не думаю, что есть более дешевый способ сделать это? Обратите внимание, что мне не важны адреса фреймов, просто их количество.

edit: эти функции ведения журнала используются во всей большой кодовой базе, поэтому ручное отслеживание глубины стека на самом деле не вариант.

Ответы [ 4 ]

5 голосов
/ 24 февраля 2009

Ходить по стеку довольно быстро - большая часть медлительности в backtrace() связана с поиском имен символов. На x86 вы можете сделать следующее:

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

Это пройдёт по цепочке ebp указателей. Имейте в виду, что это крайне непереносимо. Также обратите внимание, что при этом не будут учитываться функции, которые были встроены или оптимизированы с помощью хвостового вызова (конечно, backtrace() имеет ту же проблему).

Еще одна важная проблема - условие завершения - после возврата до main() часто нет никаких гарантий относительно того, что вы найдете в стеке. Так что, если libc не помещает нулевой указатель кадра, вы, скорее всего, будете иметь segfault. Вы можете получить значение завершения, посмотрев на него в самом начале main().

2 голосов
/ 27 февраля 2009

Для архитектур рук:

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

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

return depth;
2 голосов
/ 24 февраля 2009

Разве вы не можете просто носить с собой переменную TLS , называемую "глубиной", и увеличивать / уменьшать ее каждую функцию? Хотя вы могли бы написать свой собственный код, чтобы обходить стек быстрее, он все равно будет медленнее, чем просто переносить переменную с собой.

2 голосов
/ 24 февраля 2009

Если ваши функции симпатичной печати разумно содержатся, то передайте отступ (или размер отступа) в качестве параметра и просто увеличьте его при вызове других функций отображения.

...