2011-01-03 12 views
7

क्या निम्न कानूनी सी ++ अच्छी तरह से परिभाषित व्यवहार के साथ है?नियुक्ति के लिए भंडारण के रूप में चार सरणी

class my_class { ... }; 

int main() 
{ 
    char storage[sizeof(my_class)]; 
    new ((void *)storage) my_class(); 
} 

या क्योंकि सूचक कास्टिंग/संरेखण विवेचनाओं की इस समस्याग्रस्त है?

+0

मेरे लिए, यह ठीक है। –

+2

नहीं, उस संदर्भ में लंबवत कानूनी नहीं हैं ... (संकेत: अगर आप पूछना चाहते हैं कि कोड अच्छी तरह से परिभाषित है, तो इसे पहले संकलित करना होगा।) – GManNickG

+0

कोई भी मुझे बताएं कि उपर्युक्त चीज़ का उपयोग क्या है असली पोग्रामिंग दुनिया में। – vrbilgi

उत्तर

12

हां, यह समस्याग्रस्त है। आपको बस कोई गारंटी नहीं है कि स्मृति ठीक तरह से गठबंधन है।

उचित संरेखण के साथ भंडारण प्राप्त करने के लिए विभिन्न युक्तियां मौजूद हैं, तो आप बूस्ट या सी ++ 0x के aligned_storage का उपयोग करके सबसे अच्छे हैं, जो इन युक्तियों को आपके से छिपाते हैं।

तो फिर तुम बस जरूरत है:

// C++0x 
typedef std::aligned_storage<sizeof(my_class), 
           alignof(my_class)>::type storage_type; 

// Boost 
typedef boost::aligned_storage<sizeof(my_class), 
         boost::alignment_of<my_class>::value>::type storage_type; 

storage_type storage; // properly aligned 
new (&storage) my_class(); // okay 

ध्यान दें कि C++ 0x में, विशेषताओं का उपयोग, तो आप सिर्फ यह कर सकते हैं:

char storage [[align(my_class)]] [sizeof(my_class)]; 
+0

धन्यवाद, यह जानना बहुत उपयोगी है। – bluescarni

+0

क्षमा करें, अभी तक काफी कुछ नहीं है :) जहां तक ​​मुझे समझा गया है, भंडारण प्रकार किसी प्रकार का अंतर्निहित पूर्णांक प्रकार है। मैं इसे कैसे इस्तेमाल करूं? क्या मैं सिर्फ my_class प्रकार के लिए शून्य * के माध्यम से स्वतंत्र रूप से डाला जा सकता हूं? – bluescarni

+0

क्षमा करें, मेरा कहना था: "प्वाइंटर्स से my_class उदाहरणों के लिए स्वतंत्र रूप से आगे और आगे डालें" ... या ऐसा कुछ :) – bluescarni

2

यह संरेखण के कारण कम से कम समस्याग्रस्त है।

अधिकांश गैर-इंटेल आर्किटेक्चर पर कोड गलत संरेखण के कारण "बस त्रुटि" उत्पन्न करेगा या असीमित स्मृति पहुंच को ठीक करने के लिए आवश्यक प्रोसेसर जाल की वजह से बहुत धीमी होगी।

इंटेल आर्किटेक्चर पर यह सामान्य रूप से सामान्य से थोड़ा सा धीमा होगा। सिवाय कुछ एसएसई संचालन शामिल हैं, तो यह भी क्रैश हो सकता है।

0

char सरणी myclass के आकार के लिए सही ढंग से संरेखित नहीं किया जा सकता है। कुछ आर्किटेक्चर पर, इसका मतलब है धीमी पहुंच, और दूसरों पर, इसका मतलब है दुर्घटना। char के बजाय, आपको उस प्रकार का उपयोग करना चाहिए जिसका संरेखण struct की तुलना में बराबर या उससे अधिक है, जो इसके किसी भी सदस्यों की सबसे बड़ी संरेखण आवश्यकता द्वारा दिया जाता है।

#include <stdint.h> 

class my_class { int x; }; 

int main() { 
    uint32_t storage[size]; 
    new(storage) my_class(); 
} 

एक my_class उदाहरण के लिए पर्याप्त स्मृति को आबंटित करने के लिए, मुझे लगता है कि sizesizeof(my_class)/sizeof(T), जहां T जो भी प्रकार आप सही संरेखण प्राप्त करने के लिए उपयोग करें होना चाहिए।

+0

"... जिसका संरेखण संरचना के मुकाबले बराबर या उससे अधिक है, जो इसके किसी भी सदस्य की सबसे बड़ी संरेखण आवश्यकता द्वारा दिया जाता है" मुझे नहीं लगता कि यह गारंटी है, संरेखण पूरी तरह कार्यान्वयन-परिभाषित है। (यानी, यह संरेखण आवश्यक रूप से सख्त सदस्य के संरेखण की गारंटी नहीं है।) इसके अलावा, 'int' 32-बिट से अधिक हो सकता है। – GManNickG

+0

@GMan: आप सही हैं। हालांकि, ज्यादातर मामलों में यह काम करता है। यहां, एक लिंक है: http://stackoverflow.com/questions/364483/determining-the-alignment-of-c-c- संरचना-in-relation-to-its-members –

3

के रूप में लोगों को यहां का उल्लेख किया है, यह नहीं होगा संरेखण प्रतिबंधों के कारण जरूरी काम करते हैं। संरेखण सही पाने के कई तरीके हैं। सबसे पहले, यदि आपके पास सी ++ 0x-compliant संकलक है, तो आप संरेखण को सही करने के लिए मजबूर करने के लिए alignof ऑपरेटर का उपयोग कर सकते हैं। दूसरा, आप गतिशील रूप से चरित्र सरणी आवंटित कर सकते हैं, क्योंकि ऑपरेटर नई से स्मृति को इस तरह से गठबंधन करने की गारंटी है कि कुछ भी इसका सही ढंग से उपयोग कर सके। तीसरा, आप किसी यूनियन में वर्ण सरणी को किसी प्रकार के साथ संग्रहीत करने का प्रयास कर सकते हैं जिसमें आपके सिस्टम पर अधिकतम संभव संरेखण है; मेरा मानना ​​है कि this article पर कुछ जानकारी है (हालांकि इसे सी ++ 03 के लिए डिज़ाइन किया गया है और यह निश्चित रूप से उतना अच्छा नहीं है जितना जल्द ही बाहर आ रहा है)।

आशा है कि इससे मदद मिलती है!

2

यदि कोई बूस्ट या सी ++ 1x से बचना चाहता है, तो यह पूरा कोड जीसीसी और एमएसवीसी दोनों में काम करता है। एमएसवीसी-विशिष्ट कोड क्रोमियम के aligned_memory.h पर आधारित है। यह जीसीसी संस्करण की तुलना में थोड़ा अधिक जटिल है, क्योंकि एमएसवीसी के __declspec(align(.)) केवल शाब्दिक संरेखण मान स्वीकार करता है, और यह सभी संभावित संरेखणों के लिए टेम्पलेट विशेषज्ञता का उपयोग करके काम किया जाता है।

#ifdef _MSC_VER 

template <size_t Size, size_t Align> 
struct AlignedMemory; 

#define DECLARE_ONE_ALIGNED_MEMORY(alignment) \ 
template <size_t Size> \ 
struct __declspec(align(alignment)) AlignedMemory<Size, alignment> { \ 
    char mem[Size]; \ 
}; 

DECLARE_ONE_ALIGNED_MEMORY(1) 
DECLARE_ONE_ALIGNED_MEMORY(2) 
DECLARE_ONE_ALIGNED_MEMORY(4) 
DECLARE_ONE_ALIGNED_MEMORY(8) 
DECLARE_ONE_ALIGNED_MEMORY(16) 
DECLARE_ONE_ALIGNED_MEMORY(32) 
DECLARE_ONE_ALIGNED_MEMORY(64) 
DECLARE_ONE_ALIGNED_MEMORY(128) 
DECLARE_ONE_ALIGNED_MEMORY(256) 
DECLARE_ONE_ALIGNED_MEMORY(512) 
DECLARE_ONE_ALIGNED_MEMORY(1024) 
DECLARE_ONE_ALIGNED_MEMORY(2048) 
DECLARE_ONE_ALIGNED_MEMORY(4096) 

#else 

template <size_t Size, size_t Align> 
struct AlignedMemory { 
    char mem[Size]; 
} __attribute__((aligned(Align))); 

#endif 

template <class T> 
struct AlignedMemoryFor : public AlignedMemory<sizeof(T), __alignof(T)> {}; 
संबंधित मुद्दे