मुझे बड़ी C ++ परियोजना में अनावश्यक #include फ़ाइलों का पता कैसे लगाना चाहिए?


96

मैं विजुअल स्टूडियो 2008 में एक बड़े सी ++ प्रोजेक्ट पर काम कर रहा हूं, और अनावश्यक #includeनिर्देशों के साथ बहुत सारी फाइलें हैं । कभी-कभी #includeएस सिर्फ कलाकृतियां हैं और सब कुछ उन्हें हटाए जाने के साथ ठीक संकलित करेगा, और अन्य मामलों में कक्षाओं को आगे घोषित किया जा सकता है और # .cppफ़ाइल को स्थानांतरित किया जा सकता है । क्या इन दोनों मामलों का पता लगाने के लिए कोई अच्छा उपकरण है?

जवाबों:


50

हालांकि यह अनावश्यक फ़ाइलों को प्रकट नहीं करेगा, लेकिन दृश्य स्टूडियो में एक सेटिंग है /showIncludes( .cppफ़ाइल पर राइट क्लिक करें Properties->C/C++->Advanced) , जो संकलन समय पर सभी शामिल फ़ाइलों के एक पेड़ का उत्पादन करेगा। यह उन फ़ाइलों की पहचान करने में मदद कर सकता है जिन्हें शामिल करने की आवश्यकता नहीं है।

आप कम हेडर फ़ाइल निर्भरता के साथ दूर जाने के लिए पिंपल मुहावरे पर भी नज़र डाल सकते हैं, जिससे आप जिस क्रॉफ्ट को हटा सकते हैं, उसे देखना आसान हो जाएगा।


1
/ शोकेस बहुत अच्छा है। मैन्युअल रूप से ऐसा करना उसके बिना चुनौतीपूर्ण था।
शामबॉजिक

30

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


3
पीसी-लिंट के साथ ऐसा करने के कुछ निर्देश Riverblade.co.uk/…
डेविड साइक्स

29

एक नया क्लैंग-आधारित टूल है, जिसमें शामिल हैं-क्या-आप उपयोग करते हैं , ऐसा करने का लक्ष्य है।


ध्यान दें कि यह वर्तमान में
क्लैंग

4 जून 2015 iwyu 0.4 जारी किया गया था। यह iwyu होम पेज के अनुसार llvm + clang 3.6 के साथ संगत है ।
एरिक सोजलंड

26

!!अस्वीकरण!! मैं एक वाणिज्यिक स्थैतिक विश्लेषण उपकरण (पीसी लिंट नहीं) पर काम करता हूं। !!अस्वीकरण!!

सरल गैर पार्सिंग दृष्टिकोण के साथ कई समस्याएं हैं:

1) अधिभार सेट:

यह संभव है कि एक अतिभारित फ़ंक्शन में विभिन्न फ़ाइलों से आने वाली घोषणाएं हों। यह हो सकता है कि एक कम्पाइलर एरर के बजाय एक हेडर फाइल रिजल्ट को अलग-अलग ओवरलोड में चुना जाए! परिणाम शब्दार्थ में एक मौन परिवर्तन होगा जिसे बाद में ट्रैक करना बहुत मुश्किल हो सकता है।

2) खाका विशेषज्ञता:

ओवरलोड उदाहरण के समान, यदि आपके पास टेम्पलेट के लिए आंशिक या स्पष्ट विशेषज्ञता है, तो आप चाहते हैं कि टेम्पलेट का उपयोग होने पर वे सभी दिखाई दें। यह हो सकता है कि प्राथमिक टेम्पलेट के लिए विशेषज्ञता विभिन्न हेडर फ़ाइलों में हो। विशेषज्ञता के साथ हेडर को हटाने से एक संकलन त्रुटि नहीं होगी, लेकिन अपरिभाषित व्यवहार का परिणाम हो सकता है यदि उस विशेषज्ञता का चयन किया गया होता। (देखें: C ++ फ़ंक्शन के टेम्पलेट विशेषज्ञता की दृश्यता )

जैसा कि 'msalters' द्वारा बताया गया है, कोड का पूर्ण विश्लेषण करना भी वर्ग उपयोग के विश्लेषण की अनुमति देता है। फ़ाइलों के एक विशिष्ट पथ के रूप में एक वर्ग का उपयोग कैसे किया जाता है, यह जाँच कर, यह संभव है कि वर्ग की परिभाषा (और इसलिए इसके सभी आश्रितों को) पूरी तरह से हटाया जा सकता है या कम से कम शामिल स्तर तक मुख्य स्रोत में ले जाया जा सकता है। पेड़।


@ रीचर्ड कॉर्डन: आपका सॉफ्टवेयर (QA C ++) बहुत महंगा है।
Xander ट्यूलिप

13
@XanderTulip: बिक्री पिच में समाप्त हुए बिना इसका जवाब देना कठिन है - इसलिए मैं पहले से माफी चाहता हूं। IMHO, आपको क्या विचार करना है कि किसी भी उचित आकार की परियोजना में इस तरह की चीजों (साथ ही कई अन्य भाषा / नियंत्रण प्रवाह कीड़े) को खोजने के लिए एक अच्छा इंजीनियर कितना समय लगेगा। जैसे ही सॉफ्टवेयर बदलता है एक ही कार्य को बार-बार दोहराया जाना चाहिए। इसलिए जब आप बचाए गए समय की मात्रा में काम करते हैं तो उपकरण की लागत संभवतः महत्वपूर्ण नहीं होती है।
रिचर्ड कॉर्डन

10

मुझे ऐसे किसी भी उपकरण का पता नहीं है, और मैंने अतीत में एक लिखने के बारे में सोचा है, लेकिन यह पता चला है कि यह हल करने के लिए एक कठिन समस्या है।

अपनी स्रोत फ़ाइल में आह और bh शामिल हैं; आह होता है #define USE_FEATURE_Xऔर bh उपयोग करता है #ifdef USE_FEATURE_X। यदि #include "a.h"टिप्पणी की जाती है, तो आपकी फ़ाइल अभी भी संकलित हो सकती है, लेकिन आप जो उम्मीद करते हैं वह नहीं कर सकते हैं। इस कार्यक्रम का पता लगाना का गैर-तुच्छ है।

जो कुछ भी उपकरण करता है उसे आपके निर्माण परिवेश को भी जानना होगा। यदि आह जैसा दिखता है:

#if defined( WINNT )
   #define USE_FEATURE_X
#endif

तब USE_FEATURE_Xकेवल परिभाषित किया जाता है यदि WINNTपरिभाषित किया गया है, तो उपकरण को यह जानने की आवश्यकता होगी कि संकलक द्वारा निर्देश क्या उत्पन्न किए जाते हैं और साथ ही वे कौन से हैं जो एक शीर्षक फ़ाइल के बजाय संकलित कमांड में निर्दिष्ट किए गए हैं।


9

टिमरमैन की तरह, मैं इसके लिए किसी भी उपकरण से परिचित नहीं हूं। लेकिन मुझे पता है कि प्रोग्रामर जिन्होंने एक पर्ल (या पायथन) स्क्रिप्ट लिखी थी, जिसमें से प्रत्येक को एक बार में एक लाइन में शामिल करने की कोशिश की गई थी और फिर प्रत्येक फ़ाइल को संकलित किया।


ऐसा प्रतीत होता है कि अब एरिक रेमंड के पास इसके लिए एक उपकरण है

Google के cpplint.py में एक "शामिल है जो आप" नियम का उपयोग करते हैं (कई अन्य लोगों के बीच), लेकिन जहाँ तक मैं बता सकता हूँ, कोई भी " केवल वही उपयोग नहीं करता है जो आप उपयोग करते हैं।" फिर भी, यह उपयोगी हो सकता है।


जब मैंने इसे पढ़ा तो मुझे हँसना पड़ा। मेरे बॉस ने पिछले महीने ही हमारे एक प्रोजेक्ट पर यह काम किया। कम किए गए हेडर में कुछ कारकों द्वारा शामिल होता है।
डॉन वेकफील्ड

2
मैक पर कोडवेरियर में ऐसा करने के लिए एक स्क्रिप्ट का उपयोग किया गया था, टिप्पणी बाहर, संकलन, त्रुटि संयुक्त राष्ट्र टिप्पणी पर, #includes के अंत तक जारी रखें। यह केवल एक फ़ाइल के शीर्ष पर #includes के लिए काम करता है, लेकिन यह आमतौर पर जहां वे होते हैं। यह सही नहीं है, लेकिन यह चीजों को यथोचित रूप से सुरक्षित रखता है।
slycrel

5

यदि आप सामान्य रूप से इस विषय में रुचि रखते हैं, तो आप Lakos ' लार्ज स्केल C ++ सॉफ़्टवेयर डिज़ाइन की जाँच कर सकते हैं । यह थोड़ा सा दिनांकित है, लेकिन बहुत सारे "भौतिक डिज़ाइन" मुद्दों में चला जाता है जैसे कि हेडर की पूर्ण न्यूनतम खोजने की आवश्यकता है जिसे शामिल करने की आवश्यकता है। मैंने वास्तव में इस तरह की बात कहीं और नहीं देखी है।


4

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



3

यदि आपकी हेडर फाइलें आम तौर पर शुरू होती हैं

#ifndef __SOMEHEADER_H__
#define __SOMEHEADER_H__
// header contents
#endif

(जैसा कि #pragma का एक बार उपयोग करने के विरोध में) आप इसे बदल सकते हैं:

#ifndef __SOMEHEADER_H__
#define __SOMEHEADER_H__
// header contents
#else 
#pragma message("Someheader.h superfluously included")
#endif

और चूंकि कंपाइलर cpp फाइल का नाम संकलित करता है, इसलिए आपको कम से कम यह पता चल जाएगा कि कौन सी cpp फाइल हेडर को कई बार ला सकती है।


12
मुझे लगता है कि हेडर को कई बार शामिल करना ठीक है। जो आप उपयोग करते हैं उसे शामिल करना अच्छा है, और ऐसा करने के लिए आपकी शामिल फ़ाइलों पर निर्भर नहीं है। मुझे लगता है कि जो ओपी चाहता है वह # किन्से ढूंढना है जो वास्तव में उपयोग नहीं किया जाता है।
रयान गिन्स्ट्रोम 4

12
IMO सक्रिय रूप से गलत काम करता है। जब वे उनके बिना काम नहीं करेंगे हेडर अन्य हेडर शामिल करना चाहिए। और जब आपके पास है A.hऔर आप B.hदोनों पर निर्भर हैं C.hऔर आप शामिल हैं A.hऔर B.h, क्योंकि आपको दोनों की आवश्यकता है, तो आप दो बार शामिल होंगेC.h , लेकिन यह ठीक है, क्योंकि संकलक इसे दूसरी बार छोड़ देगा और यदि आप नहीं करते हैं, तो आपको याद रखना होगा। हमेशा C.hपहले A.hया B.hबहुत अधिक बेकार समावेशन को समाप्त करने के लिए शामिल करें।
Jan Hudec

5
सामग्री सटीक है, यह हेडर खोजने के लिए एक अच्छा समाधान है जो कई बार शामिल किए जाते हैं। हालाँकि, मूल प्रश्न का उत्तर इसके द्वारा नहीं दिया गया है और मैं कल्पना नहीं कर सकता कि यह कब एक अच्छा विचार होगा। सीपीपी फाइलों में वे सभी हेडर शामिल होने चाहिए, जिन पर वे निर्भर हैं, भले ही हेडर कहीं और से पहले शामिल किया गया हो। आप नहीं चाहते हैं कि आपकी परियोजना विशिष्ट रूप से संकलित हो या मान लें कि किसी भिन्न हेडर में आपकी आवश्यकता शामिल होगी।
जयपब

3

पीसी-लिंट वास्तव में ऐसा कर सकते हैं। ऐसा करने का एक आसान तरीका यह है कि इसे अप्रयुक्त का पता लगाने के लिए कॉन्फ़िगर किया जाए जिसमें फाइलें शामिल हैं और अन्य सभी मुद्दों को अनदेखा करें। यह बहुत सीधा है - केवल संदेश 766 को सक्षम करने के लिए ("मॉड्यूल में हेडर फ़ाइल का उपयोग नहीं किया जाता है"), बस कमांड लाइन पर -w0 + e766 विकल्प शामिल करें।

इसी दृष्टिकोण का उपयोग संबंधित संदेशों जैसे 964 ("हेडर सीधे मॉड्यूल में उपयोग नहीं की गई") और 966 ("अप्रत्यक्ष रूप से शामिल हेडर फ़ाइल मॉड्यूल में उपयोग नहीं किया जाता है") के साथ भी किया जा सकता है।

FWIW I ने पिछले हफ्ते http://www.riverblade.co.uk/blog.php?archive=2008_09_01_archive.xml#3575027665614914318 पर एक ब्लॉग पोस्ट में इस बारे में और विस्तार से लिखा ।


2

यदि आप #includeबिल्ड समय को कम करने के लिए अनावश्यक फ़ाइलों को हटाने के लिए देख रहे हैं , तो आपका समय और पैसा बेहतर हो सकता है , ताकि आप अपनी बिल्ड प्रक्रिया को cl.exe / MP , make -j , Xoreax IncrediBuild , distcc / icecream का उपयोग करके बेहतर बना सकें। , इत्यादि ।

बेशक, यदि आपके पास पहले से ही एक समानांतर निर्माण प्रक्रिया है और आप अभी भी इसे गति देने की कोशिश कर रहे हैं, तो हर तरह से अपने #includeनिर्देशों को साफ करें और उन अनावश्यक निर्भरता को दूर करें।


2

प्रत्येक शामिल फ़ाइल के साथ शुरू करें, और सुनिश्चित करें कि प्रत्येक फ़ाइल में केवल वही शामिल है जो खुद को संकलित करने के लिए आवश्यक है। कोई भी फ़ाइलें जो तब C ++ फ़ाइलों के लिए अनुपलब्ध हैं, उन्हें C ++ फ़ाइलों में स्वयं जोड़ा जा सकता है।

प्रत्येक शामिल और स्रोत फ़ाइल के लिए, प्रत्येक में एक बार एक फ़ाइल शामिल करें और देखें कि क्या वह संकलन करता है।

वर्णमाला में शामिल फ़ाइलों को क्रमबद्ध करना भी एक अच्छा विचार है, और जहां यह संभव नहीं है, एक टिप्पणी जोड़ें।


2
मुझे यकीन नहीं है कि यह टिप्पणी कितनी व्यावहारिक है, अगर बहुत बड़ी संख्या में कार्यान्वयन फाइलें शामिल हैं।
सन्नी

1

निम्नलिखित #defines में से एक या दोनों को जोड़ना अक्सर अनावश्यक हेडर फ़ाइलों को बाहर कर देगा और विशेष रूप से संकलन समय में सुधार कर सकता है, खासकर अगर वह कोड जो विंडोज एपीआई फ़ंक्शन का उपयोग नहीं कर रहा है।

#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN

Http://support.microsoft.com/kb/166474 देखें


1
दोनों की कोई आवश्यकता नहीं - VC_EXTRALEAN को परिभाषित करता है Win32_LEAN_AND_MEAN
Aidan Ryan

1

यदि आप पहले से ही नहीं हैं, तो सब कुछ शामिल करने के लिए एक precompiled हेडर का उपयोग करना, जिसे आप बदलने नहीं जा रहे हैं (प्लेटफ़ॉर्म हेडर, बाहरी एसडीके हेडर, या स्थिर आपकी परियोजना के पहले से ही पूर्ण टुकड़े) बिल्ड समय में एक बड़ा अंतर लाएगा।

http://msdn.microsoft.com/en-us/library/szfdksca(VS.71).aspx

इसके अलावा, हालांकि आपकी परियोजना के लिए बहुत देर हो सकती है, अपनी परियोजना को अनुभागों में व्यवस्थित करना और सभी स्थानीय हेडर को एक बड़े मुख्य हेडर में नहीं देना एक अच्छा अभ्यास है, हालांकि इसमें थोड़ा अतिरिक्त काम लगता है।


Precompiled हेडर की महान व्याख्या: cygnus-software.com/papers/precompiledheaders.html (सुनिश्चित करें कि यदि precompiled हेडर ऑटोजेनरेटेड हेडर विज़ुअलस्टडियो के हाल के संस्करणों में टूट गया है, लेकिन यह जाँच के लायक है।)
idririi

1

यदि आप ग्रहण सीडीटी के साथ काम करेंगे तो आप अपनी संरचना को शामिल करने के लिए http://includator.com की कोशिश कर सकते हैं। हालाँकि, कुलपति के बारे में पर्याप्त रूप से पता नहीं हो सकता है VC ++ के पूर्वनिर्धारित में शामिल हैं और VCT का उपयोग करने के लिए CDT की स्थापना सही शामिल है, अभी तक CDT में निर्मित नहीं है।


1

नवीनतम Jetbrains IDE, CLion, स्वचालित रूप से दिखाता है (ग्रे में) जिसमें वर्तमान फ़ाइल में उपयोग नहीं किया जाता है।

आईडीई से सभी अप्रयुक्त की सूची (और भी फ़ंक्शन, विधियाँ, आदि ...) भी संभव है।


0

कुछ मौजूदा उत्तर बताते हैं कि यह कठिन है। यह वास्तव में सच है, क्योंकि आपको उन मामलों का पता लगाने के लिए एक पूर्ण संकलक की आवश्यकता होती है जिसमें एक आगे की घोषणा उपयुक्त होगी। आप C ++ को यह जानने के बिना बता सकते हैं कि प्रतीकों का क्या अर्थ है; व्याकरण बस इसके लिए बहुत अस्पष्ट है। आपको पता होना चाहिए कि क्या एक निश्चित नाम एक वर्ग का नाम देता है (आगे घोषित किया जा सकता है) या एक चर (नहीं)। इसके अलावा, आपको नाम-पता होना चाहिए।


आप सिर्फ यह कह सकते हैं कि "यह निर्णय लेना कि कौन सा # आवश्यक है, हल करने की समस्या को हल करने के बराबर है। शुभकामनाएँ :)" बेशक, आप उत्तराधिकार का उपयोग कर सकते हैं, लेकिन मुझे ऐसा करने वाले किसी भी मुफ्त सॉफ़्टवेयर का पता नहीं है।
पोर्स

0

हो सकता है कि थोड़ी देर हो गई, लेकिन मुझे एक बार एक WebKit पर्ल स्क्रिप्ट मिली, जो आपको चाहिए थी। मुझे लगता है मुझे यकीन है कि कुछ अच्छा करने की आवश्यकता होगी (मैं पर्ल में अच्छी तरह से वाकिफ नहीं हूँ), लेकिन यह चाल करना चाहिए:

http://trac.webkit.org/browser/branches/old/safari-3-2-branch/WebKitTools/Scripts/find-extra-includes

(यह एक पुरानी शाखा है क्योंकि ट्रंक में अब फ़ाइल नहीं है)


0

यदि कोई विशेष शीर्षलेख है जो आपको लगता है कि अब और ज़रूरत नहीं है (string.h कहें), तो आप यह टिप्पणी कर सकते हैं कि इसमें शामिल हैं, फिर इसे नीचे शामिल करें:

#ifdef _STRING_H_
#  error string.h is included indirectly
#endif

बेशक आपके इंटरफ़ेस हेडर सीपीपी मेमोरी में उनके समावेश को रिकॉर्ड करने के लिए एक अलग #define सम्मेलन का उपयोग कर सकते हैं। या कोई सम्मेलन नहीं, जिस स्थिति में यह दृष्टिकोण काम नहीं करेगा।

फिर पुनर्निर्माण। तीन संभावनाएं हैं:

  • यह ठीक बनाता है। string.h संकलित-महत्वपूर्ण नहीं था, और इसके लिए शामिल को हटाया जा सकता है।

  • # यात्राएं। string.g को अप्रत्यक्ष रूप से किसी तरह शामिल किया गया था यदि आप अभी भी नहीं जानते हैं कि string.h की आवश्यकता है। यदि यह आवश्यक है, तो आपको इसे सीधे देखना चाहिए (नीचे देखें)।

  • आपको कुछ अन्य संकलन त्रुटि मिलती है। string.h की आवश्यकता थी और इसे अप्रत्यक्ष रूप से शामिल नहीं किया जा रहा था, इसलिए इसे शामिल करना शुरू करने के लिए सही था।

ध्यान दें कि अप्रत्यक्ष रूप से शामिल किए जाने पर निर्भर करता है जब आपका .h या .c सीधे दूसरे का उपयोग करता है। यह लगभग निश्चित रूप से एक बग है: आप इस बात का वादा कर रहे हैं कि आपके कोड को केवल उस हेडर की आवश्यकता होगी जब तक कि आप उपयोग कर रहे कुछ अन्य हेडर की आवश्यकता होती है। जो शायद तुम्हारा मतलब नहीं है।

हेडर के बारे में अन्य उत्तरों में उल्लिखित कैवियट, जो व्यवहार को संशोधित करते हैं, जो कि असफलताओं का कारण बनने वाली चीजों को यहां भी लागू करते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.