Получить стек вызовов в коде с меньшими накладными расходами?

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

  •  22-07-2019
  •  | 
  •  

Вопрос

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

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

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

Спасибо.

Это было полезно?

Решение

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

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;" заставит вас просмотреть стек (если вам нужно больше этой трассировки стека).

Другие советы

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

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

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

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

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

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

Гилад

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

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

Есть какие-нибудь комментарии?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top