2011-12-09 16 views
5

Próbuję przechwycić stos wywołań tak szybko, jak to możliwe. Teraz to, co mam:Szybkie przechwytywanie stosu wywołań

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

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

ten jest przeznaczony do użytku w systemie śledzenia pamięci, dlatego tak perfekcyjnie, że skończę z tablicą adresów jeśli mogą później (po pewnym napędzany przez użytkownika zdarzenia) zostać przekształconym w coś, co jest czytelne dla człowieka.

  • Jak mogę skręcić addrs w coś czytelnej dla człowieka? (patrz edycja poniżej)
  • Czy jest coś szybszego niż RtlCaptureStackBackTrace?
  • Czy istnieje sposób przechodzenia między platformami w celu przechwycenia stosu wywołań?

Edit:

Odwróciłem adresy do ludzkiej czytelnej informacji za pomocą SymFromAddr i SymGetLineFromAddr64. Jednak moja wersja new, która używa CaptureStackBackTrace, trwa ~ 30 razy dłużej niż oryginał i prawie cały czas jest ze względu na ślad stosu. Wciąż szukam szybszego rozwiązania!

Odpowiedz

2

Czy istnieje sposób przechodzenia między platformami w celu przechwycenia stosu wywołań?

Szybka odpowiedź brzmi, że niestety nie jest to możliwe. Różne kompilatory i platformy będą inaczej organizować stos, a bez "pomocy" z kompilatora, nie będziesz w stanie dokładnie prześledzić z powrotem stosu ... co można zrobić na platformach, które używają stosu frame base-pointer byłoby przesunięcie do góry stosu używając wartości w EBP lub RBP, a nawet to zależy od tego, czy korzystasz z 32-bitowego pliku wykonywalnego x86, czy też z pliku wykonywalnego x86_64. Dodatkowo zasady rządzące aplikacją UNIX - interfejs binarny (ABI) i Windows ABI są zupełnie inne. Tak w ogóle, masz zamiar skończyć się koniecznością wspierania co najmniej cztery różne możliwości:

  1. Unix 32-bitowe ABI
  2. Unix 64-bitowe ABI
  3. systemu Windows 32-bitowe ABI
  4. Windows 64-bitowy ABI

Należy pamiętać, że 64-bitowy układ ABI systemu UNIX umożliwia kompilatorom wybór, czy będą obsługiwać wskaźnik bazowy stosu, czy też nie, a więc korzystanie z bazy danych wskaźnik nie jest gwarantowany; kompilator może po prostu wybrać odniesienie wszystkich zmiennych stosu do samego wskaźnika stosu bez użycia oddzielnej wskazówki bazowej. Byłoby to nadal uważane za zgodne z 64-bitowym ABI UNIX.

Jak widać, przy wszystkich tych możliwych odmianach, będziesz mieć bardzo trudny czas na stworzenie niezawodnego licznika stosu między platformami. Najlepiej, jeśli chcesz korzystać z narzędzi dostępnych dla platformy, na którą kierujesz reklamy. Jeśli potrzebujesz obsługi wielu platform, to niestety będzie pewien poziom duplikacji kodu, ponieważ korzystasz z narzędzi specyficznych dla platformy, aby pomóc niezawodnie wykonać śledzenie stosu.

0

Nie ma międzyplatformowego sposobu, ale istnieją wieloplatformowe biblioteki, które działają. It's a common requirement for garbage collectors.

Niestety, nie wiem wystarczająco dużo o tych bibliotekach, aby je polecić. MMgc ma coś osadzonego (wyjaśnione w linku powyżej). Jestem pewien, że śmieciarz Hansa Boehma ma jeszcze jedną.

Biblioteki te będą generalnie opierać się na połączeniach specyficznych dla platformy, takich jak RtlCaptureStackBacktrace w systemie Windows. Byłbym zdumiony, gdyby jakakolwiek taka biblioteka poszła szybciej niż połączenia specyficzne dla platformy; ale byłbym też zdumiony, gdyby jakakolwiek taka biblioteka poszła znacznie wolniej. Jedyne pytanie - do mnie - brzmiałoby, czy wolisz wywoływać wywołanie API Windows bezpośrednio, czy też przekierować to połączenie przez inną bibliotekę.

Powiązane problemy