2009-08-05 5 views
2

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

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

Прокомментирован любой комментарий.

Спасибо.

+1

Как насчет перефразировать ваш «вопрос» в реальный вопрос? – Bombe

+2

Вы всегда можете просто смотреть на valgrinds source. [http://valgrind.org/downloads/] – GManNickG

+0

edited. Извините за нечеткое описание. – limi

ответ

2

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

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

большое спасибо. Это то, что мне нравится. – limi

4

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

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

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

Для получения более подробной информации см. man backtrace.

0

Остерегайтесь рекурсий с помощью backtrace_symbols(), который вызывает сам malloc.

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

Gilad

0

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

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

Любые комментарии?

+0

на 64-битной, теперь я использую backtrace() – limi