जब इसका उपयोग नहीं किया जाता है तो स्टैक मेमोरी क्यों आवंटित की जाती है?


14

निम्नलिखित उदाहरण पर विचार करें:

struct vector {
    int  size() const;
    bool empty() const;
};

bool vector::empty() const
{
    return size() == 0;
}

के लिए उत्पन्न विधानसभा कोड vector::empty(अनुकूलन के साथ, क्लेंग द्वारा):

push    rax
call    vector::size() const
test    eax, eax
sete    al
pop     rcx
ret

यह स्टैक स्पेस क्यों आवंटित करता है? इसका उपयोग बिल्कुल नहीं किया जाता है। pushऔर popहटाया जा सकता है। MSVC के अनुकूलित बिल्ड और gcc भी इस फ़ंक्शन के लिए स्टैक स्पेस का उपयोग करते हैं ( गॉडबोल्ट पर देखें ), इसलिए एक कारण होना चाहिए।


7
क्या आपने निहित thisपैरामीटर के लिए खाता है ?
०४

1
@ याकूब: नहीं। मुझे क्यों करना चाहिए? vector::size()उदाहरण के लिए यह अनुकरण करने के लिए परिभाषित नहीं है कि यह इनलेट नहीं है।
डॉ। गुट

1
तो, एक संकलक कुछ ऐसा कैसे अनुकूलित कर सकता है जो यह नहीं जानता है?
Bob__

1
@ याकूब: मुझे लगता है, यह जानना कि कार्यान्वयन के vector::size()लिए प्रासंगिक नहीं है या इसके लिए स्टैक फ्रेम आवंटित नहीं करना है vector::empty()। इसमें empty()सिर्फ यह कहा जाता है, चाहे वह कुछ भी हो।
डॉ। गुट

1
ठीक है, आप एक फ़ंक्शन को कॉल कर रहे हैं जो कुछ देता है, आपको उसके लिए स्थान की आवश्यकता है (यदि आप कोई बेहतर नहीं जानते हैं)।
Bob__

जवाबों:


11

यह स्टैक स्पेस आवंटित करता है, इसलिए स्टैक 16-बाइट गठबंधन है। इसकी आवश्यकता है, क्योंकि वापसी पता 8 बाइट्स लेता है, इसलिए स्टैक 16-बाइट को संरेखित रखने के लिए अतिरिक्त 8 बाइट स्थान की आवश्यकता होती है।

स्टैक फ्रेम के संरेखण को कुछ संकलक के लिए कमांड लाइन तर्कों के साथ कॉन्फ़िगर किया जा सकता है।

  • MSVC : प्रलेखन कहता है कि स्टैक हमेशा 16-बाइट के साथ संरेखित होता है। कोई भी कमांड लाइन तर्क इसे बदल नहीं सकता है। गॉडबोल्ट उदाहरण से पता चलता है कि rspफ़ंक्शन की शुरुआत में 40 बाइट्स को घटाया जाता है , जिसका अर्थ है कि कुछ और भी इसे प्रभावित करता है।
  • क्लैंग : -mstack-alignmentविकल्प स्टैक संरेखण को निर्दिष्ट करता है। ऐसा लगता है, कि डिफ़ॉल्ट 16 है, हालांकि प्रलेखित नहीं है। यदि आप इसे 8 पर सेट करते हैं, तो स्टैक आवंटन ( pushऔर pop) उत्पन्न विधानसभा कोड से गायब हो जाता है।
  • gcc : -mpreferred-stack-boundaryविकल्प स्टैक अलाइनमेंट को निर्दिष्ट करता है। यदि दिया गया मान N है, तो इसका अर्थ है 2 ^ N संरेखण की बाइट्स। डिफ़ॉल्ट मान 4 है, जिसका अर्थ है 16 बाइट्स। यदि आप इसे 3 (यानी 8 बाइट्स) पर सेट करते हैं, तो स्टैक आवंटन ( subऔर इसके addलिए)rsp जनरेट असेंबली कोड) से गायब हो जाता है।

Godbolt पर देखें


यही कारण है कि c ++ गुरु, विशेषज्ञ हमेशा चेतावनी देते रहे हैं: सबसे छोटे / सबसे बड़े आकार के क्रम में स्ट्रक्चर / क्लास के सदस्यों को छोटा करने के लिए ... केवल इस तरह से यह सही ढंग से कुशल होगा
नॉक

@geza: धन्यवाद। मैंने अन्य दो संकलक के लिए कुछ शोध किया, और आपके उत्तर के लिए इसे लिखा। क्या आपको यह पसंद है?
डॉ। गुट

1
@ Dr.Gut: धन्यवाद, आपने उत्तर को बहुत बेहतर और पूर्ण बना दिया है। ध्यान दें, कि स्टैक अलाइनमेंट आमतौर पर सिस्टम के लिए एबीआई में प्रलेखित होता है (उदाहरण के लिए, कुछ सिस्टम के लिए, यहाँ दस्तावेज़ हैं: github.com/hjl-tools/x86-psABI/wiki/X86-psABI )।
जीजा

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