2012-02-22 21 views
7

निम्नलिखित कोड पर विचार करें:जीसीसी अलग-अलग क्षेत्रों में स्थानीय यूनियनों के लिए अलग-अलग स्टैक स्पेस आवंटित क्यों करता है?

#include <stdlib.h> 

#ifndef TRY 
#define TRY struct 
#endif 

TRY testme 
{ 
    int one; 
    int two; 
    char three; 
    int four; 
}; 

int 
main (void) 
{ 
    { 
    volatile TRY testme one; 

    one.one = 2; 
    one.three = 7; 
    } 

    { 
    volatile TRY testme twos; 

    twos.one = 3; 
    } 

    { 
    volatile TRY testme one; 

    one.one = 4; 
    } 

    { 
    volatile TRY testme twos; 

    twos.one = 5; 
    } 

    { 
    volatile TRY testme twos; 

    twos.one = 6; 
    } 

    { 
    volatile TRY testme twos; 

    twos.one = 6; 
    } 

    return EXIT_SUCCESS; 
} 

संकलित रूप में 86 के लिए है (जिसका अर्थ है testme एक struct है), ढेर आकार संकलक मुख्य के लिए आवंटित 16 बाइट्स है।

$ gcc -DTRY=union -g -O2 test.c -o test 
$ objdump -d ./test | ./checkstack.pl i386 | grep main 

इसके अलावा, struct के किसी भी अतिरिक्त उदाहरण:

$ gcc -g -O2 test.c -o test 
$ objdump -d ./test | ./checkstack.pl i386 | grep main 
16 main 

हालांकि, TRY संघ को परिभाषित के साथ संकलित (जिसका अर्थ है testme एक संघ है), ढेर आकार संकलक मुख्य के लिए आवंटित 32 बाइट्स/अतिरिक्त क्षेत्रों में परिभाषित संघ, संघ का उपयोग करते समय बड़े ढेर आवंटन का उत्पादन करेगा, लेकिन संरचना के रूप में उपयोग किए जाने पर स्टैक आवंटन को विस्तारित नहीं करेगा।

अब, यह समझ में नहीं आता है - संघ को कम स्टैक स्पेस लेना चाहिए, अगर नहीं, तो अधिक नहीं, फिर एक ही फ़ील्ड के साथ एक संरचना!

ऐसा लगता है जैसे जीसीसी यूनियनों को अलग-अलग क्षेत्रों में भी समवर्ती रूप से उपयोग करता है, लेकिन structs के लिए ऐसा नहीं करता है।

कुछ और स्पष्टीकरण:

  1. अस्थिर दूर कार्य के अनुकूलन से संकलक को रोकने के लिए प्रयोग किया जाता है। अस्थिरता को खोना और अनुकूलन के साथ संकलन एक ही परिणाम उत्पन्न करता है।

  2. भले ही टेस्टमे एक ऐसी संरचना है जिसमें सदस्यों में से एक के रूप में संघ है, वही व्यवहार देखा जाता है। दूसरे शब्दों में - यह पर्याप्त है कि संरचना के सदस्यों में से एक अलग-अलग स्टैक आवंटन के लिए जीसीसी के लिए एक संघ है।

  3. कंपाइलर जीसीसी संस्करण 4.4.3 (उबंटू 4.4.3-4ubuntu5) है लेकिन अन्य आर्किटेक्चर के लिए अन्य जीसीसी संस्करणों ने वही व्यवहार दिखाया है।

  4. checkstack.pl केवल स्टैक आवंटित करने के लिए उपयोग किए गए निर्देशों के लिए objdump आउटपुट की खोज करता है (स्टैक पॉइंटर से सब)।

मेरा प्रश्न:

  1. क्यों जीसीसी इस करता है? क्या यह एक बग है या इस व्यवहार के लिए कोई कारण है?
  2. मान लीजिए कि यह एक बग नहीं है, क्या इसके आसपास काम करने का एक तरीका है और यूनियनों के समान स्टैक्ट्स के लिए स्टैक आवंटित करने के लिए जीसीसी को मजबूर करना है।

स्पष्टीकरण: क्यों struct या संघ अपनी ओर के आकार से आकार में बड़ा हो गया लगता है मेरा प्रश्न नहीं है। मैं समझता हूं कि संरेखण के लिए पैडिंग का कारण है। मेरी समस्या यह है कि संकलक यूनियन के विभिन्न उदाहरणों के लिए एकाधिक स्टैक फ्रेम आवंटित करता है, भले ही उन्हें विभिन्न क्षेत्रों में परिभाषित किया गया हो, जबकि यह नहीं होना चाहिए और वास्तव में एक ही फ़ील्ड के साथ संरचना के लिए ऐसा नहीं करना चाहिए।

धन्यवाद!

+0

हो सकता है कि यूनियनों के साथ-साथ '-O2' (अभी तक) पर अनुकूलित नहीं कर रहे हैं? जेनरेट असेंबलर कोड पर एक नज़र डालें। 'सख्त-एलियासिंग' को अक्षम करने का भी प्रयास करें। ओह, और एक मौजूदा जीसीसी आज़माएं। –

+1

क्या आपने [इस सवाल] पर एक नज़र डाली है (http://stackoverflow.com/questions/8453881/sizeof-union-larger-than-expected-how-does-type-alignment-take-place-here) और [ यह एक] (http://stackoverflow.com/questions/7212585/why-is-my-unions-size-bigger-than-i-expected)? ऐसा लगता है कि पैडिंग और संरेखण बाधाओं का मामला – Coren

+0

@ एनी-मूस -फनो-सख्त-एलियासिंग एक ही परिणाम उत्पन्न करता है। मैं परीक्षण करने के लिए नवीनतम जीसीसी का निर्माण कर रहा हूँ। – gby

उत्तर

8

स्पष्ट रूप से यूनियनों के संबंध में जीसीसी के सख्त एलियासिंग परावर्तक को आराम करने के लिए कम से कम एक प्रयास किया गया है।

आप यह सुनिश्चित करें कि जीसीसी स्रोत आप से या समकक्ष पैच आवेदन किया है संकलन करना चाहते हो सकता है: http://codereview.appspot.com/4444051/

+0

यही वही है जो मैं ढूंढ रहा था। बहुत बहुत धन्यवाद :-) – gby

0

यह पैडिंग और इंट की मूल डिफ़ॉल्ट आकार परिभाषा की तरह दिखता है।

32 में बिट स्मृति नक्शा होगा: एक (2 बाइट्स) दो (2 बाइट्स) तीन (1 बाइट) (1 बाइट) गद्दी चार (2 बाइट्स)

कुल - 8 बाइट्स।

64 में

सा यह हो जाएगा: एक (4 बाइट्स) दो (4 बाइट्स) तीन (1 बाइट) (3 बाइट्स गद्दी) चार (4 बाइट्स)

कुल - 16 बाइट्स।

यदि आप "int" से "छोटा int" बदलते हैं, तो स्मृति अलग दिखाई देगी।

+1

लेकिन 'यूनियन' के रूप में, पूरी चीज केवल 4 बाइट्स लेनी चाहिए, भले ही यह 32 या 64 बिट हो। –

+0

मुझे कोई समस्या नहीं है कि एक ही संरचना या संघ कितना लेता है। मेरी समस्या यह है कि जीसीसी अलग-अलग क्षेत्रों में परिभाषित यूनियन के विभिन्न उदाहरणों के लिए अलग-अलग स्टैक स्पेस आवंटित करता प्रतीत होता है, भले ही इसे ऐसा करने की आवश्यकता न हो और वास्तव में यह संरचना – gby

+0

के लिए ऐसा न करे, फिर भी संघ के रूप में यह अगले आने पर निर्भर करता है। यदि यह संघ की सरणी के अंदर है - यह 64 बिट के तहत भी 32 बिट ले जाएगा।यदि यह परिवर्तनीय है, तो 64 बिट सिस्टम पर इसे 64 बिट्स पर गद्देदार किया जाएगा। यह दायरा नहीं है, यह "अगला क्या आता है"। –

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

  • कोई संबंधित समस्या नहीं^_^