簡體   English   中英

快速捕獲調用堆棧

[英]Capture the call stack quickly

我正試圖盡快捕獲調用堆棧。 現在這就是我所擁有的:

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

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

這是用於內存跟蹤系統,所以如果以后(在一些用戶驅動的事件上)可以變成人類可讀的東西,我最終會得到一個地址數組。

  • 如何將 addrs變成人類可讀的東西? (見下面的編輯)
  • 有沒有比RtlCaptureStackBackTrace更快的RtlCaptureStackBackTrace
  • 是否有跨平台方式來捕獲調用堆棧?

編輯:

我使用SymFromAddrSymGetLineFromAddr64將地址轉換為人類可讀信息。 但是,我使用CaptureStackBackTracenew版本比原始版本長了大約30倍,幾乎所有時間都是因為堆棧跟蹤。 我還在尋找更快的解決方案!

是否有跨平台方式來捕獲調用堆棧?

答案很簡單,不幸的是,這是不可能的。 不同的編譯器和平台將以不同的方式組織堆棧,如果沒有編譯器的“幫助”,您將無法准確地追溯堆棧...您可以在使用堆棧的平台上做的最多 - frame base-pointer將使用EBPRBP的值向上移動堆棧,甚至取決於您運行的是32位x86可執行文件還是x86_64可執行文件。 此外,管理UNIX應用程序二進制接口(ABI)和Windows ABI的規則完全不同。 所以一般來說,你最終必須支持至少四種不同的可能性:

  1. Unix 32位ABI
  2. Unix 64位ABI
  3. Windows 32位ABI
  4. Windows 64位ABI

請記住,UNIX 64位ABI允許編譯器選擇是否支持堆棧幀基指針...因此不保證使用基指針; 編譯器可以簡單地選擇在不使用單獨的基指針的情況下針對堆棧指針本身引用所有堆棧變量。 這仍然被認為符合UNIX 64位ABI。

正如您所看到的,通過所有這些可能的變化,您將非常難以制作可靠的跨平台堆棧跟蹤器。 您最好選擇使用可用於您所針對的平台的工具。 如果您需要支持多個平台,那么不幸的是,當您使用特定於平台的工具來幫助您可靠地執行堆棧跟蹤時,將會出現一定程度的代碼重復。

沒有跨平台的方式,但有一些跨平台的庫可以解決這個問題。 這是垃圾收集器的常見要求

不幸的是,我對這些庫的推薦不夠了解。 MMgc有嵌入的東西(在上面的鏈接中解釋)。 我敢肯定Hans Boehm的垃圾收集器有另一個。

通常,這些庫將依賴於特定於平台的調用,例如Windows上的RtlCaptureStackBacktrace 如果任何這樣的庫比特定於平台的調用更快,我會感到驚訝; 但是如果任何這樣的庫變得非常慢,我也會感到驚訝。 對我來說,唯一的問題是你是想直接調用Windows API調用還是通過另一個庫來調用該調用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM