C ++ का प्रारंभिक आवंटन C के मुकाबले इतना बड़ा क्यों है?


138

एक ही कोड का उपयोग करते समय, बस कंपाइलर (C कंपाइलर से C ++ कंपाइलर तक) को बदलने से मेमोरी कितनी आवंटित होती है, बदल जाएगी। मुझे यकीन नहीं है कि यह क्यों है और इसे और अधिक समझना चाहते हैं। अब तक मुझे जो सबसे अच्छी प्रतिक्रिया मिली है, वह है "शायद I / O स्ट्रीम", जो बहुत वर्णनात्मक नहीं है और मुझे C ++ के "पहलू जो आप उपयोग नहीं करते हैं, उसके बारे में आपको आश्चर्य नहीं है"।

मैं क्रमशः Clang और GCC कंपाइलर, संस्करण 7.0.1-8 और 8.3.0-6 का उपयोग कर रहा हूं। मेरा सिस्टम डेबियन 10 (बस्टर), नवीनतम पर चल रहा है। बेंचमार्क Valgrind Massif के माध्यम से किया जाता है।

#include <stdio.h>

int main() {
    printf("Hello, world!\n");
    return 0;
}

उपयोग किया गया कोड परिवर्तित नहीं होता है, लेकिन मैं C या C ++ के रूप में संकलित करता हूं, तो यह Valgrind मानदंड के परिणामों को बदल देता है। हालाँकि, मान कंपाइलर के अनुरूप होते हैं। कार्यक्रम के लिए रनटाइम आबंटन (शिखर) निम्नानुसार है:

  • जीसीसी (C): 1,032 बाइट्स (1 KB)
  • G ++ (C ++): 73,744 बाइट्स, (~ 74 KB)
  • क्लैंग (C): 1,032 बाइट्स (1 KB)
  • क्लैंग ++ (C ++): 73,744 बाइट्स (~ 74 KB)

संकलन के लिए, मैं निम्नलिखित आदेशों का उपयोग करता हूं:

clang -O3 -o c-clang ./main.c
gcc -O3 -o c-gcc ./main.c
clang++ -O3 -o cpp-clang ./main.cpp
g++ -O3 -o cpp-gcc ./main.cpp

Valgrind के लिए, मैं valgrind --tool=massif --massif-out-file=m_compiler_lang ./compiler-langप्रत्येक संकलक और भाषा पर चलता हूं , फिर ms_printचोटियों को प्रदर्शित करने के लिए।

क्या मुझसे यहां कुछ गलत हो रहा है?


11
शुरू करने के लिए, आप कैसे निर्माण कर रहे हैं? आप किन विकल्पों का उपयोग करते हैं? और आप कैसे मापते हैं? आप वाल्ग्रिंड कैसे चलाते हैं?
कुछ प्रोग्रामर ने

17
अगर मुझे सही से याद है, तो आधुनिक C ++ कंपाइलर्स में एक अपवाद मॉडल होता है, जहां tryएक बड़ी मेमोरी फुटप्रिंट की कीमत पर एक ब्लॉक में प्रवेश करने के लिए कोई प्रदर्शन हिट नहीं होता है , शायद एक जंप टेबल या कुछ और के साथ। शायद अपवादों के बिना संकलन करने की कोशिश करें और देखें कि क्या प्रभाव पड़ता है। संपादित करें: वास्तव में, iteratively विभिन्न सी ++ सुविधाओं को अक्षम करने की कोशिश करते हैं कि मेमोरी फुटप्रिंट पर क्या प्रभाव पड़ता है।
फ्रैंकोइस एंड्रीक्स

3
जब clang++ -xcइसके बजाय के साथ संकलित किया clangगया था, तो वही आवंटन था, जो लिंक किए गए पुस्तकालयों के कारण दृढ़ता से सुझाव देता है
जस्टिन

14
@bigwillydos यह वास्तव में C ++ है, मुझे C ++ विनिर्देशों का कोई भी हिस्सा दिखाई नहीं देता है जो इसे तोड़ता है ... संभवतः cddio के बजाय stdio.h सहित अन्य लेकिन यह कम से कम पुराने C ++ संस्करण में अनुमत है। आपको क्या लगता है कि इस कार्यक्रम में "विकृत" क्या है?
वैलेटी

4
मुझे यह संदेहास्पद लगता है कि उन gcc और clang कंपाइलर Cमोड में बाइट्स की सटीक संख्या और बाइट्स C++मोड की सटीक समान संख्या उत्पन्न करते हैं । क्या आपने एक प्रतिलेखन त्रुटि की?
रॉनजॉन

जवाबों:


149

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

g ++ -Wl, - as-need main.cpp

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

आप इसे C फ़ाइल के साथ भी देख सकते हैं। यदि आप इसका संकलन करते हैं:

gcc main.c -lstdc ++

ढेर उपयोग फिर से दिखाई देगा, भले ही आपने सी प्रोग्राम बनाया हो।

हीप उपयोग स्पष्ट रूप से आपके द्वारा उपयोग किए जा रहे विशिष्ट C ++ लाइब्रेरी कार्यान्वयन पर निर्भर है। आपके मामले में, यह GNU C ++ लाइब्रेरी, libstdc ++ है । अन्य कार्यान्वयन समान मात्रा में मेमोरी आवंटित नहीं कर सकते हैं, या वे किसी भी मेमोरी को आवंटित नहीं कर सकते हैं (कम से कम स्टार्टअप पर नहीं।) उदाहरण के लिए LLVM C ++ लाइब्रेरी ( libc ++ ) स्टार्टअप पर कम से कम, मेरे लिनक्स पर आवंटन आवंटित नहीं करता है। मशीन:

clang ++ -stdlib = libc ++ main.cpp

हीप का उपयोग समान है जो इसके खिलाफ बिल्कुल भी लिंक नहीं करता है।

(यदि संकलन विफल हो जाता है, तो libc ++ शायद स्थापित नहीं है। पैकेज नाम में आमतौर पर "libc ++" या "libcc" होता है।)


50
इस उत्तर को देखने पर, मेरा पहला विचार है, " यदि यह ध्वज अनावश्यक ओवरहेड को कम करने में मदद करता है, तो यह डिफ़ॉल्ट रूप से क्यों नहीं है ।" क्या इसका कोई अच्छा जवाब है?
नट

4
@ मेरा अनुमान देव समय पर संकलन करने के लिए धीमा है। जब आप एक रिलीज़ बिल्ड बनाने के लिए तैयार होते हैं तो आप उसे चालू कर देते हैं। एक सामान्य / बड़े कोडबेस में भी अंतर न्यूनतम हो सकता है (यदि आप बहुत सारे एसटीडी लाइब्रेरी आदि का उपयोग कर रहे हैं)
DarcyThomas

24
@ नोट -Wl,--as-neededफ्लैग पुस्तकालयों को हटाता है जिन्हें आप अपने -lझंडे में निर्दिष्ट करते हैं लेकिन आप वास्तव में उपयोग नहीं कर रहे हैं। इसलिए यदि आप एक पुस्तकालय का उपयोग नहीं करते हैं, तो बस इसके खिलाफ लिंक न करें। इसके लिए आपको इस ध्वज की आवश्यकता नहीं है हालाँकि, यदि आपका बिल्ड सिस्टम बहुत सारे पुस्तकालयों को जोड़ता है और यह उन सभी को साफ करने के लिए बहुत काम आएगा और केवल उन लोगों को लिंक करेगा, तो आप इस ध्वज का उपयोग कर सकते हैं। मानक पुस्तकालय एक अपवाद है, हालांकि, यह स्वचालित रूप से खिलाफ जुड़ा हुआ है। तो यह एक कोने का मामला है।
निकोस सी।

36
@ नट -आस की जरूरत के लिए अवांछित साइडइफेक्ट्स हो सकते हैं, यह जाँच करके काम करता है कि क्या आप किसी लाइब्रेरी के प्रतीक का उपयोग करते हैं और उन लोगों को मारते हैं जो परीक्षण में विफल रहते हैं। BUT: एक पुस्तकालय विभिन्न चीजों को भी निहित कर सकता है, उदाहरण के लिए, यदि आपके पास लाइब्रेरी में एक स्थिर C ++ उदाहरण है, तो इसके निर्माता को स्वचालित रूप से कहा जाएगा। ऐसे दुर्लभ मामले हैं जहां एक पुस्तकालय जिसे आप स्पष्ट रूप से कॉल नहीं करते हैं आवश्यक है, लेकिन वे मौजूद हैं।
नोर्बर्ट लैंग

3
@NikosC। बिल्ड-सिस्टम स्वचालित रूप से नहीं जानता कि आपके एप्लिकेशन कौन से प्रतीकों का उपयोग करता है, और कौन से पुस्तकालय उन्हें लागू करते हैं (कंपाइलर, आर्क, डिस्ट्रो और सी / सी ++ लाइब्रेरी के बीच भिन्न होता है)। आधार रनटाइम लाइब्रेरियों के लिए कम से कम, बल्कि परेशानी बहुत कम है। लेकिन दुर्लभ मामलों के लिए आपको एक पुस्तकालय की आवश्यकता होती है, आपको बस उस एक के लिए -नो-अस-आवश् यकता का उपयोग करना चाहिए, और हर जगह -सा-आवश्यक छोड़ना चाहिए। एक usecase मैंने देखा कि अनुरेखण / डिबगिंग (lttng) और पुस्तकालयों के लिए पुस्तकालय हैं जो प्रमाणीकरण / जोड़ने के प्रकार का कुछ करते हैं।
नॉर्बर्ट लैंग

16

न तो जीसीसी और न ही क्लैंग कंपाइलर हैं - वे वास्तव में टूलचैन ड्राइवर प्रोग्राम हैं। इसका मतलब है कि वे संकलक, कोडांतरक और लिंकर का आह्वान करते हैं।

यदि आप अपने कोड को C या C ++ कंपाइलर के साथ संकलित करते हैं तो आपको वही असेंबली मिल जाएगी। असेंबलर समान वस्तुओं का उत्पादन करेगा। अंतर यह है कि टूलचैन चालक दो अलग-अलग भाषाओं के लिए लिंकर को अलग-अलग इनपुट प्रदान करेगा: अलग-अलग स्टार्टअप (सी ++ को नेमस्पेस स्तर पर स्थिर या थ्रेड-लोकल स्टोरेज अवधि वाले ऑब्जेक्ट के लिए कंस्ट्रक्टर और डिस्ट्रक्टर्स को निष्पादित करने के लिए कोड की आवश्यकता होती है, और स्टैक के लिए बुनियादी ढांचे की आवश्यकता होती है) अपवाद प्रसंस्करण के दौरान फ्रेमिंग का समर्थन करने के लिए फ्रेम, उदाहरण के लिए), सी ++ मानक पुस्तकालय (जिसमें नामस्थान स्तर पर स्थिर भंडारण अवधि की वस्तुएं भी हैं), और शायद अतिरिक्त रनटाइम लाइब्रेरीज़ (उदाहरण के लिए, इसके स्टैक-अनइंडिंग इन्फ्रास्ट्रक्चर के साथ libgcc)।

संक्षेप में, यह संकलक नहीं है, जो पदचिह्न में वृद्धि का कारण है, यह आपके द्वारा चुनी गई सामग्री का लिंक है जो C ++ भाषा को चुनकर उपयोग करना है।

यह सच है कि C ++ में "केवल आपके द्वारा उपयोग किए जाने वाले दर्शन के लिए भुगतान है", लेकिन भाषा का उपयोग करके, आप इसके लिए भुगतान करते हैं। आप भाषा के कुछ हिस्सों (RTTI, अपवाद हैंडलिंग) को अक्षम कर सकते हैं लेकिन फिर आप C ++ का उपयोग नहीं कर रहे हैं। जैसा कि एक अन्य उत्तर में उल्लेख किया गया है, यदि आप मानक पुस्तकालय का उपयोग बिल्कुल नहीं करते हैं, तो आप ड्राइवर को निर्देश दे सकते हैं कि वह (- डब्ल्यूएल, - आवश्यकतानुसार) छोड़ दें लेकिन यदि आप किसी भी सुविधा का उपयोग नहीं करने जा रहे हैं C ++ या इसकी लाइब्रेरी में, आप प्रोग्रामिंग भाषा के रूप में C ++ भी क्यों चुन रहे हैं?


तथ्य यह है कि अपवाद को संभालने में सक्षम होने पर भी एक लागत होती है यदि आप वास्तव में इसका उपयोग नहीं करते हैं तो यह एक समस्या है। यह सामान्य रूप से C ++ सुविधाओं के लिए सामान्य नहीं है, और यह कुछ ऐसा है जो C ++ मानकों के कार्य समूहों को ठीक करने के तरीकों के बारे में सोचने की कोशिश कर रहा है। एसीसीयू 2019 डी-टुकड़ा-टुकड़ा सी में हर्ब सटर की मुख्य चर्चा देखें : अपवादों को अधिक सस्ती और उपयोगी बनाना । यह एक दुर्भाग्यपूर्ण तथ्य है, हालांकि, वर्तमान सी ++ में। और पारंपरिक C ++ अपवादों में हमेशा वह लागत होगी, भले ही / जब नए अपवादों के लिए नए तंत्र एक कीवर्ड के साथ जोड़े जाएं।
पीटर कॉर्डेस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.