Получить стек вызовов в коде с меньшими издержками? - PullRequest
2 голосов
/ 05 августа 2009

Я собираюсь реализовать внутренний профилировщик для памяти на Linux. Я хочу сохранить стек для каждого malloc / free / realloc. Я пытаюсь использовать «pstack» для получения трассировки стека каждый раз. Но накладные расходы слишком высоки. Есть ли какой-нибудь подход lightweigt для получения стека вызовов в C-коде?

Я знаю, что есть некоторые инструменты, такие как "valgrind, google profiler", но не знаю, как они запоминают стеки для каждого действия.

Любой комментарий приветствуется.

Спасибо.

Ответы [ 4 ]

4 голосов
/ 05 августа 2009

Существует функция GNU backtrace(), которая относительно быстра - она ​​просто возвращает массив адресов.

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

Чтобы получить backtrace_symbols() на самом деле разрешить имена, вам нужно использовать -rdynamic опции компоновщика.

Подробнее см. man backtrace.

2 голосов
/ 05 августа 2009

Вы можете сделать свою собственную функцию для получения звонящего:

static inline void *get_caller(void) {
    unsigned long *ebp;

    /* WARNING: This is working only with frame pointers */
    asm ("movl %%ebp, %0" : "=r" (ebp) : );
    ebp = (unsigned long*)*ebp;
    ebp = (unsigned long*)*(ebp+1);
    return ebp;
}

void *malloc(void) {
    void *caller = get_caller();
    ...    
}

"ebp = (unsigned long*)*ebp;" заставит вас пройти через стек (если вам нужно больше этой трассировки стека).

0 голосов
/ 14 августа 2009

Теперь я сталкиваюсь с проблемой на 64-битной.

На 64-битной основе RBP не поддерживается строго. Например, gcc -O3 будет использовать RBP в качестве обычного сохраненного регистра вызывающего абонента. Так что в этом случае получить стеки вызовов из указателей фреймов не получается. :(

Есть комментарии?

0 голосов
/ 09 августа 2009

Следите за рекурсиями с помощью backtrace_symbols (), которая сама вызывает malloc.

Также обратите внимание, что при первом использовании backtrace () и друзей динамический компоновщик попытается загрузить libgcc, который снова вызовет malloc.

Гилад

...