2011-08-14 5 views
7

मैं gcov टूल के आउटपुट को समझने की कोशिश कर रहा हूं। इसे बिना किसी विकल्प के चलाना समझ में आता है, लेकिन मैं शाखा कवरेज विकल्पों को आजमाकर समझना चाहता हूं। दुर्भाग्य से यह समझना मुश्किल है कि शाखाएं क्या करती हैं और उन्हें क्यों नहीं लिया जाता है। नीचे एक विधि के लिए आउटपुट है (नवीनतम एलएलवीएम/क्लैंग बिल्ड का उपयोग करके संकलित करें)। , एक खाली सरणी, 1 वस्तु के साथ एक सरणी और सरणी 2 वस्तुओं के साथ और 4 वस्तुओं के साथ एक सरणीgcov फ़ाइलों में शाखाओं को समझना

function -[TestCoverageAppDelegate loopThroughArray:] called 5 returned 100% blocks executed 88% 
     5: 30:- (NSInteger)loopThroughArray:(NSArray *)array { 
     5: 31: NSInteger i = 0; 
     22: 32: for (NSString *string in array) { 
branch 0 taken 0 
branch 1 taken 7 
     -: 33:   
     22: 34: } 
branch 0 taken 4 
branch 1 taken 3 
branch 2 taken 0 
branch 3 taken 3 
     5: 35: return i; 
     -: 36:} 

मैं इस के माध्यम से 5 परीक्षण चलाने की है, शून्य में गुजर। मुझे लगता है कि पहले मामले में, शाखा 1 का अर्थ है "लूप में जाना" लेकिन मुझे कोई संकेत नहीं है कि शाखा 0 क्या है। दूसरे मामले में शाखा 0 फिर से लूप प्रतीत होता है, शाखा 1 लूप समाप्त हो रहा है और शाखा 3 लूप से बाहर/बाहर निकल रहा है, लेकिन मुझे नहीं पता कि शाखा 2 क्या है या क्यों/इसे कब निष्पादित किया जाएगा।

यदि कोई जानता है कि शाखा की जानकारी को कैसे समझें, या किसी भी विस्तृत दस्तावेज़ीकरण के बारे में क्या पता है, तो मैं मदद की सराहना करता हूं।

+0

अपने फ़ंक्शन की असेंबली प्राप्त करने का प्रयास करें और इसमें 'j **' निर्देशों की संख्या जांचें। – osgx

+0

मेरी असेंबली बहुत अच्छी नहीं है लेकिन ऐसा लगता है कि 4 हैं। पहला एक जे है जो मुझे लगता है कि लूप पर छोड़ने पर कोई ऑब्जेक्ट नहीं है। फिर एक और जे जो एक गणना उत्परिवर्तन अपवाद पर छोड़ देता है, एक जेबी जिसे मुझे नहीं पता है, लेकिन लूप के शीर्ष पर वापस चला जाता है और फिर एक जेन जो मुझे लगता है कि लूप के शीर्ष पर चलता है यदि गणना करने के लिए वस्तुओं को छोड़ दिया जाता है। दिलचस्प बात यह है कि उत्परिवर्तन पहली शाखा 0 को लेने का कारण बनता है, जो एक रहस्य हल करता है, लेकिन शाखा 2 अभी भी मुझे –

+0

हम्म को बढ़ाता है .. अन्य संभावित मामला ऑब्जेक्ट फ़ाइल को अलग करना है, जिसे '-pg' (gcov चलने के लिए) के साथ संकलित किया गया था। आपको इस तरह के disassembly में कुछ gcov उपकरण कार्यों के लिए कॉल देखना चाहिए .. "__llvm_gcov_ctr" वृद्धि या "__llvm_gcda_edge" कॉल की तरह smth। साथ ही, क्या आपने 'ओ0' पर' -फनो-इनलाइन 'के साथ संकलित किया था? – osgx

उत्तर

3

जीसीओवी मशीन कमांड के हर मूल ब्लॉक (आप संकलक के बारे में सोच सकते हैं) के उपकरण (संकलन करते समय) द्वारा काम करता है। Basic block का मतलब कोड का एक रैखिक खंड है, जिसमें इसके अंदर कोई शाखा नहीं है और इसके अंदर कोई लेबल नहीं है। इसलिए, यदि और केवल यदि आप मूल ब्लॉक चलाने शुरू करते हैं, तो आप मूल ब्लॉक के अंत तक पहुंच जाएंगे। सीएफजी में नियंत्रण ब्लॉक आयोजित किए जाते हैं (नियंत्रण प्रवाह ग्राफ, इसके बारे में निर्देशित ग्राफ के रूप में सोचें), जो मूलभूत ब्लॉक्स के बीच संबंध दिखाता है (V1 से V2 तक बढ़त V1 V2 कॉल करता है; और V2 को V1 द्वारा बुलाया जाता है)। तो, profile-arcs कंपाइलर और जीसीओवी मोड प्रत्येक पंक्ति के लिए निष्पादन गिनती प्राप्त करना चाहते हैं और मूल ब्लॉक निष्पादन की गणना के माध्यम से ऐसा करना चाहते हैं। सीएफजी में कुछ किनारों का वाद्य यंत्र है और कुछ नहीं हैं, क्योंकि ग्राफ़ में मूल ब्लॉक के बीच बीजगणितीय संबंध हैं।

आपका ओबीजेसी निर्माण (for..in) कम हो गया है (शुरुआती संकलन में परिवर्तित) कई बुनियादी ब्लॉक में। तो, gcov 4 शाखाओं को देखता है, क्योंकि यह केवल बीबीएस कम देखता है। यह इस कम करने के बारे में कुछ भी नहीं जानता है, लेकिन यह जानता है कि कौन सी रेखा प्रत्येक असेंबलर निर्देश से मेल खाती है (यह डीबग जानकारी है)। तो, शाखाएं सीएफजी के किनारों हैं।

यदि आप मूलभूत ब्लॉक देखना चाहते हैं, तो आपको संकलित प्रोग्राम के एक असेंबलर डंप करना चाहिए या कंपाइलर से बाइनरी या डंप सीएफजी को अलग करना चाहिए। आप इसे profile-arcs और गैर-profile-arcs मोड दोनों के लिए कर सकते हैं और उनकी तुलना कर सकते हैं।

profile-arcs मोड में "__llvm_gcov_ctr" या "__llvm_gcda_edge" जैसी कुछ कॉल और वृद्धि होगी - यह मूलभूत ब्लॉक का वास्तविक साधन है।

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