Obter a pilha de chamadas em código com menos sobrecarga?
Pergunta
Eu estou indo para implementar um profiler interna para a memória no linux. Eu quero salvar a pilha para cada malloc / free / realloc. Eu estou tentando usar "pstack" para obter a toda rastreamento de pilha. Mas a sobrecarga é muito alta. Existe alguma abordagem lightweigt para obter a pilha de chamadas em código C?
Eu sei que existem algumas ferramentas como "valgrind, google profiler", mas não sei como eles remebmer as pilhas para cada ação.
Qualquer comentário é apreciado.
Graças.
Solução
Você pode fazer a sua própria função para obter o chamador:
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;
" vai fazer você passar pela pilha (se precisar de mais do que rastreamento de pilha).
Outras dicas
Há uma função backtrace()
GNU que é relativamente rápido -. Ele só retorna matriz de endereços
Para resolver esses endereços para nomes de função você precisa usar backtrace_symbols()
que é muito mais pesado, mas espero que você não precisa executá-lo muitas vezes.
Para obter backtrace_symbols()
realmente resolver nomes você precisa usar as opções de vinculador -rdynamic
.
Veja man backtrace
para mais detalhes.
Cuidado com recursions com backtrace_symbols (), que chama malloc si.
Observe também que na primeira utilização do registo de chamadas () e amigos do vinculador dinâmico tentará libgcc carga, o que vai mais uma vez invocar malloc.
Gilad
Agora eu me encontro com um problema em 64 bits.
Em 64 bits, RBP não é estritamente mantida. Por exemplo, gcc O3 usará RBP como um chamador normal, salvo se cadastrar. Portanto, neste caso, para obter pilhas de chamadas de ponteiros do quadro não funciona:. (
Algum comentário?