2010-09-28 21 views
14

के बीच सीएलआर ऑब्जेक्ट आकार को समझना मैं 32 बिट और 64 बिट प्रोसेसर के बीच ऑब्जेक्ट आकार अंतर को समझने की कोशिश कर रहा हूं। मान लीजिए कि मैं एक साधारण वर्ग32 बिट बनाम 64 बिट

class MyClass 
{ 
    int x; 
    int y; 
} 
एक 32 बिट मशीन पर

तो करते हैं, एक पूर्णांक 4 बाइट है। अगर मैं इसमें सिंकब्लॉक जोड़ता हूं (एक और 4 बाइट्स), ऑब्जेक्ट का आकार 12 बाइट होगा। यह 16 बाइट क्यों दिखा रहा है?

 
0:000> !do 0x029d8b98 
Name: ConsoleApplication1.Program+MyClass 
MethodTable: 000e33b0 
EEClass: 000e149c 
Size: 16(0x10) bytes 
(C:\MyTemp\ConsoleApplication1\ConsoleApplication1\bin\x86\Debug\ConsoleApplication1.exe) 
Fields: 
     MT Field Offset     Type VT  Attr Value Name 
71972d70 4000003  4   System.Int32 1 instance  0 x 
71972d70 4000004  8   System.Int32 1 instance  0 y 

एक 64 बिट मशीन पर, एक पूर्णांक अब भी है 4 बाइट केवल एक चीज बदल कि Syncblock 8 बाइट्स हो जाएगा (के रूप में संकेत दिए गए 64 बिट मशीनों पर 8 बाइट्स हैं)। इसका मतलब है कि वस्तु का आकार 16 बाइट होगा। यह 24 बाइट क्यों दिखा रहा है?

 
0:000> !do 0x00000000028f3c90 
Name: ConsoleApplication1.Program+MyClass 
MethodTable: 000007ff00043af8 
EEClass: 000007ff00182408 
Size: 24(0x18) bytes 
(C:\MyTemp\ConsoleApplication1\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe) 
Fields: 
       MT Field Offset     Type VT  Attr   Value Name 
000007fef4edd998 4000003  8   System.Int32 1 instance    0 x 
000007fef4edd998 4000004  c   System.Int32 1 instance    0 y 

उत्तर

24

सीएलआर मेमोरी में ऑब्जेक्ट्स को फिट करने के लिए स्वतंत्र है जैसा फिट बैठता है। यह एक कार्यान्वयन विस्तार है। आपको किसी विशिष्ट लेआउट पर भरोसा नहीं करना चाहिए।

जो अंतर आप देखते हैं वह गायब टाइपहैंडल फ़ील्ड के कारण है जो सीएलआर ऑब्जेक्ट हेडर का हिस्सा भी है। इसके अतिरिक्त, फ़ील्ड बाइट सीमाओं के साथ गठबंधन किया जा सकता है।


Advanced .Net Debugging - CLR Object’s Internal Structure से

:

वस्तु का CLR आंतरिक संरचना है:

[DWORD: SyncBlock] [DWORD: MethodTable सूचक] [DWORD: संदर्भ प्रकार सूचक] ... मूल्य की [मान प्रकार फ़ील्ड] ...

वस्तु हैडर: [DWORD: SyncBlock]
वस्तु सूचक: [DWORD: MethodTable सूचक] [DWORD: संदर्भ प्रकार सूचक] ... [मूल्य प्रकार फ़ील्ड का मान] ...

हर वस्तु (किसी ऋणात्मक ऑफ़सेट पर) एक ObjHeader से पहले किया गया है। ObjHeader में सिंकब्लॉक के लिए एक अनुक्रमणिका है।


तो अपने वस्तु की संभावना इस तरह खर्च की गई थी:

: (8 बाइट्स गठबंधन)

 
    Syncblk  TypeHandle  X   Y 
------------,------------|------------,------------| 
         8       16 

: (8 बाइट्स गठबंधन)

 
     Syncblk     TypeHandle    X   Y 
-------------------------|-------------------------|------------,------------| 
         8       16      24 

यह भी देखें: Drill Into .NET Framework Internals to See How the CLR Creates Runtime Objects

0

वस्तुओं सदस्य चर परे कुछ भूमि के ऊपर है। .NET के 32-बिट कार्यान्वयन में, आवंटन ओवरहेड 12 बाइट्स प्रतीत होता है। जैसा कि मुझे याद है, यह 64 बिट रनटाइम में 16 बाइट्स है।

इसके अतिरिक्त, ऑब्जेक्ट आवंटन अगले 8 बाइट सीमा पर गठबंधन किया गया है।

+0

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

+0

ऑब्जेक्ट के बाहर किसी भी ओवरहेड के बारे में विवरण इस मामले में वास्तव में प्रासंगिक नहीं हैं। उस ओवरहेड का अधिकांश भाग वस्तु में ऑब्जेक्ट टेबल में होता है, ऑब्जेक्ट पर नहीं। – cHao

0

मुझे लगता है, किसी भी वस्तु को अपनी कक्षा में किसी प्रकार का सूचक होना चाहिए। यह आपके अतिरिक्त 4 या 8 बाइट्स के लिए खाता होगा।

किसी वस्तु का लेआउट वास्तव में एक कार्यान्वयन की बात है, हालांकि। यदि आप लेआउट की परवाह करते हैं, तो ऐसे गुण हैं जो स्पष्ट रूप से बताए गए हैं कि नेट कहां और कैसे आप सदस्यों को चाहते हैं। StructLayoutAttribute देखें।

7

सिंक ब्लॉक ऑब्जेक्ट पॉइंटर से नकारात्मक ऑफसेट पर बैठता है। ऑफसेट 0 पर पहला फ़ील्ड विधि तालिका सूचक, x64 पर 8 बाइट्स है। तो x86 पर यह एसबी + एमटी + एक्स + वाई = 4 + 4 + 4 + 4 = 16 बाइट्स है। सिंक ब्लॉक इंडेक्स अभी भी x64 में 4 बाइट्स है। लेकिन ऑब्जेक्ट हेडर भी कचरा इकट्ठा कचरे में भाग लेता है, इसे जारी किए जाने के बाद एक लिंक्ड सूची में नोड के रूप में कार्य करता है। इसके लिए एक बैक और फॉरवर्ड पॉइंटर की आवश्यकता होती है, प्रत्येक 8 बाइट x64 में, इस प्रकार ऑब्जेक्ट पॉइंटर से पहले 8 बाइट की आवश्यकता होती है। 8 + 8 + 4 + 4 = 24 बाइट्स।

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