2011-12-09 21 views
5

मैं जितनी जल्दी हो सके कॉल स्टैक को कैप्चर करने की कोशिश कर रहा हूं। अभी यह है कि मैं क्या मिल गया है है:कॉल स्टैक को तुरंत कैप्चर करें

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 से कुछ भी तेज है?
  • क्या कॉल स्टैक को पकड़ने के लिए एक क्रॉस प्लेटफ़ॉर्म तरीका है?

संपादित करें:

मैं SymFromAddr और SymGetLineFromAddr64 का उपयोग करके मानव पठनीय जानकारी में पते बदल गया। हालांकि, new का मेरा संस्करण CaptureStackBackTrace का उपयोग करता है जो मूल से ~ 30x लंबा होता है और लगभग हर समय स्टैक ट्रेस के कारण होता है। मैं अभी भी एक तेज समाधान की तलाश में हूँ!

उत्तर

2

क्या कॉल स्टैक को पकड़ने के लिए एक क्रॉस प्लेटफ़ॉर्म तरीका है?

त्वरित उत्तर यह है कि दुर्भाग्य से यह संभव नहीं है। विभिन्न कंपाइलर और प्लेटफॉर्म अलग-अलग ढेर को व्यवस्थित करेंगे, और कंपाइलर से "सहायता" के बिना, आप स्टैक के माध्यम से सटीक रूप से पीछे का पता लगाने में सक्षम नहीं होंगे ... सबसे अधिक आप प्लेटफॉर्म पर कर सकते हैं जो स्टैक- फ्रेम बेस-पॉइंटर EBP या RBP में मानों का उपयोग करके स्टैक को ऊपर ले जाना होगा, और यह भी निर्भर है कि आप 32-बिट x86 निष्पादन योग्य या x86_64 निष्पादन योग्य चल रहे हैं या नहीं। इसके अतिरिक्त यूनिक्स एप्लिकेशन-बाइनरी-इंटरफेस (एबीआई) और विंडोज एबीआई को नियंत्रित करने वाले नियम पूरी तरह से अलग हैं।

  1. यूनिक्स 32-बिट ABI
  2. यूनिक्स 64-बिट ABI
  3. Windows 32-bit ABI
  4. : तो सामान्य तौर पर, आप कम से कम चार अलग अलग संभावनाएं समर्थन करने के लिए होने अंत करने जा रहे हैं Windows 64-bit ABI

ध्यान रखें कि यूनिक्स 64-बिट ABI compilers के लिए अनुमति देता है कि क्या वे करेंगे या एक ढेर फ्रेम आधार सूचक का समर्थन नहीं करेंगे चुनने के लिए ... इसलिए एक base- के उपयोग सूचक की गारंटी नहीं है; एक कंपाइलर केवल अलग-अलग बेस-पॉइंटर का उपयोग किए बिना स्टैक-पॉइंटर के खिलाफ सभी स्टैक-चर के संदर्भ में चयन कर सकता है। यह अभी भी यूनिक्स 64-बिट एबीआई के साथ अनुपालन माना जाएगा।

तो जैसा कि आप देख सकते हैं, इन सभी संभावित विविधताओं के साथ, आपको एक विश्वसनीय क्रॉस-प्लेटफार्म स्टैक-ट्रैसर बनाने में बहुत कठिन समय होगा। आपके द्वारा लक्षित प्लेटफॉर्म के लिए उपलब्ध टूल का उपयोग करने के लिए यह सबसे अच्छा शर्त है। यदि आपको कई प्लेटफार्मों का समर्थन करने की आवश्यकता है, तो दुर्भाग्यवश कुछ स्तर कोड कोड डुप्लिकेशंस होने जा रहा है क्योंकि आप स्टैण्ड-ट्रेस को विश्वसनीय रूप से करने में आपकी सहायता के लिए प्लेटफ़ॉर्म-विशिष्ट टूल का उपयोग करते हैं।

0

क्रॉस-प्लेटफ़ॉर्म तरीका नहीं है, लेकिन क्रॉस-प्लेटफ़ॉर्म लाइब्रेरीज़ हैं जो चाल करते हैं। It's a common requirement for garbage collectors

दुर्भाग्यवश, मुझे इन पुस्तकालयों के बारे में पर्याप्त जानकारी नहीं है। एमएमजीसी में कुछ एम्बेडेड है (उपरोक्त लिंक में समझाया गया है)। मुझे यकीन है कि हंस बोहेम के कचरा कलेक्टर के पास दूसरा है।

ये पुस्तकालय सामान्य रूप से प्लेटफ़ॉर्म-विशिष्ट कॉल पर भरोसा करेंगे, जैसे कि RtlCaptureStackBacktrace विंडोज पर। अगर कोई ऐसी लाइब्रेरी प्लेटफार्म-विशिष्ट कॉल से तेज हो तो मैं आश्चर्यचकित हूं; लेकिन अगर कोई ऐसी लाइब्रेरी काफी धीमी हो गई तो मैं भी आश्चर्यचकित होगा। एकमात्र सवाल - मेरे लिए - क्या आप Windows API कॉल को सीधे कॉल करना चाहते हैं या किसी अन्य लाइब्रेरी के माध्यम से कॉल करने के लिए रूट करना चाहते हैं।

संबंधित मुद्दे