2011-12-09 22 views
5

Sto provando a catturare lo stack di chiamate il più rapidamente possibile. In questo momento questo è quello che ho:Cattura rapidamente lo stack di chiamate

void* addrs[10] = {}; 
DWORD hash; 
RtlCaptureStackBackTrace(0, 10, addrs, &hash); 

for(size_t i = 0; i <10; ++i) 
{ 
    std::cout << addrs[i] << '\n'; 
} 

Questo è per l'uso in un sistema di tracciamento di memoria, quindi è perfettamente bene che io alla fine con una serie di indirizzi, se possono in seguito (su qualche guidata dall'utente evento) essere trasformato in qualcosa di leggibile.

  • Come posso trasformare addrs in qualcosa di leggibile? (vedi modifica sotto)
  • C'è qualcosa più veloce di RtlCaptureStackBackTrace?
  • Esiste un modo multipiattaforma per acquisire lo stack di chiamate?

Edit:

ho girato gli indirizzi in informazioni leggibili umano usando SymFromAddr e SymGetLineFromAddr64. Tuttavia, la mia versione di CaptureStackBackTrace che utilizza CaptureStackBackTrace richiede circa 30 volte di più dell'originale e quasi tutto il tempo è dovuto alla traccia dello stack. Sto ancora cercando una soluzione più veloce!

risposta

2

Esiste un modo multipiattaforma per acquisire lo stack di chiamate?

La risposta rapida è che purtroppo non è possibile. Diversi compilatori e piattaforme organizzeranno lo stack in modo diverso e senza "aiuto" dal compilatore, non sarete in grado di risalire esattamente nello stack ... il massimo che potreste fare sulle piattaforme che usano uno stack- frame-pointer dovrebbe essere spostarsi sullo stack usando i valori in EBP o RBP, e anche quello dipende da se si sta eseguendo un eseguibile x86 a 32 bit o un eseguibile x86_64. Inoltre, le regole che regolano l'interfaccia binaria dell'applicazione (ABI) e l'ABI di Windows sono completamente diverse. Quindi, in generale, si sta andando a finire per dover sostenere almeno quattro diverse possibilità:

  1. Unix a 32 bit ABI
  2. Unix a 64 bit ABI
  3. Windows a 32-bit ABI
  4. Windows a 64-bit ABI

Tenete a mente che l'UNIX a 64 bit ABI consente per i compilatori di scegliere se lo faranno o non vuole sostenere una base-stack pointer-frame ... quindi l'uso di un base- il puntatore non è garantito; un compilatore può semplicemente scegliere di fare riferimento a tutte le variabili stack rispetto allo stack-pointer stesso senza utilizzare un puntatore base separato. Questo sarebbe comunque considerato compatibile con l'ABI 64 bit di UNIX.

Quindi, come potete vedere, con tutte queste possibili variazioni, avrete un momento molto difficile fare un affidabile tracer-stacker multipiattaforma. La tua migliore scommessa per utilizzare gli strumenti disponibili per la piattaforma che stai prendendo di mira. Se hai bisogno di supportare più piattaforme, sfortunatamente ci sarà un certo livello di duplicazione del codice quando utilizzerai strumenti specifici della piattaforma per aiutarti a eseguire in modo affidabile lo stack-trace.

0

Non c'è un modo multipiattaforma, ma esistono librerie multipiattaforma che fanno il trucco. It's a common requirement for garbage collectors.

Sfortunatamente, non ne so abbastanza di queste librerie per raccomandarne uno. MMgc ha qualcosa di incorporato (spiegato nel link, sopra). Sono sicuro che il netturbino di Hans Boehm ne ha un altro.

Queste librerie, in generale, si baseranno su chiamate specifiche della piattaforma, come ad esempio RtlCaptureStackBacktrace su Windows. Sarei stupito se una tale libreria fosse più veloce delle chiamate specifiche della piattaforma; ma sarei anche stupito se una libreria di questo tipo diventasse molto più lenta. L'unica domanda - per me - sarebbe se preferisci chiamare direttamente la chiamata API di Windows o indirizzare quella chiamata attraverso un'altra libreria.

Problemi correlati