क्या C ++ में अधिकतम सरणी की लंबाई सीमा है?


183

क्या C ++ में किसी सरणी के लिए अधिकतम लंबाई है?

क्या यह C ++ सीमा है या यह मेरी मशीन पर निर्भर करता है? क्या यह ट्विक है? क्या यह उस प्रकार पर निर्भर करता है जिस प्रकार सरणी से बना है?

क्या मैं उस सीमा को किसी तरह से तोड़ सकता हूं या मुझे जानकारी संग्रहीत करने के बेहतर तरीके की तलाश करनी होगी? और सबसे सरल तरीका क्या होना चाहिए?

मुझे क्या करना है एक सरणी पर लंबे लंबे इंट स्टोर कर रहा है, मैं एक लिनक्स वातावरण में काम कर रहा हूं। मेरा प्रश्न है: अगर मुझे एन> 10 अंकों के साथ एन लंबे लंबे पूर्णांक की एक सरणी को स्टोर करने की आवश्यकता है तो मुझे क्या करना होगा?

मुझे इसकी आवश्यकता है क्योंकि मैं स्कूल के लिए कुछ क्रिप्टोग्राफ़िक एल्गोरिथ्म (उदाहरण के लिए पी-पोलार्ड) लिख रहा हूं, और पूर्णांक की इस दीवार और एरेस प्रतिनिधित्व की लंबाई मारा।

जवाबों:


163

दो सीमाएं हैं, दोनों को C ++ द्वारा लागू नहीं किया गया है, बल्कि हार्डवेयर द्वारा।

पहली सीमा (जिस तक कभी नहीं पहुंचनी चाहिए) को सरणी (और आकार में परिवर्तन) में एक सूचकांक का वर्णन करने के लिए उपयोग किए जाने वाले आकार प्रकार के प्रतिबंधों द्वारा निर्धारित किया जाता है। यह सिस्टम के अधिकतम मूल्य द्वारा दिया std::size_tजा सकता है। यह डेटा प्रकार किसी भी वस्तु के बाइट्स में आकार को सम्‍मिलित करने के लिए काफी बड़ा है

अन्य सीमा एक भौतिक मेमोरी सीमा है। सरणी में आपकी ऑब्जेक्ट जितनी बड़ी होती हैं, उतनी ही जल्दी यह सीमा पूरी हो जाती है क्योंकि मेमोरी भर जाती है। उदाहरण के लिए, vector<int>दिए गए आकार n में से एक आम तौर पर कई बार अधिक मेमोरी लेता है एक प्रकार की सरणी के रूप में vector<char>(एक छोटे से स्थिर मान माइनस), क्योंकि intआमतौर पर इससे बड़ा होता है char। इसलिए, vector<char>हो सकता है vector<int>कि पहले से भरा स्मृति की तुलना में अधिक आइटम हो सकते हैं । कच्चे सी-स्टाइल सरणियों के लिए समान मायने रखता है जैसे int[]और char[]

इसके अतिरिक्त, इस ऊपरी सीमा का allocatorउपयोग करने के प्रकार से प्रभावित किया जा सकता है vectorक्योंकि allocatorयह किसी भी तरह से मेमोरी को प्रबंधित करने के लिए स्वतंत्र है। एक बहुत ही अजीब लेकिन फिर भी बोधगम्य आवंटनकर्ता इस तरह से मेमोरी को पूल कर सकता है कि ऑब्जेक्ट शेयर संसाधनों के समान उदाहरण। इस तरह, आप एक कंटेनर में कई समान वस्तुओं को सम्मिलित कर सकते हैं जो अन्यथा सभी उपलब्ध मेमोरी का उपयोग करेंगे।

इसके अलावा, C ++ किसी भी सीमा को लागू नहीं करता है।


20
इसके अलावा, आप आम तौर पर आसानी से स्टैक आकार सीमा को मार सकते हैं, खासकर यदि थ्रेड्स का उपयोग करके जो फिर से विशिष्ट है (लेकिन बदला जा सकता है)।
अलारिक

@ सहयोगी: सच है। मैं सिस्टम विशेष में बहुत गहराई तक नहीं जाना चाहता था क्योंकि वे बहुत भिन्न होते हैं और मैं उनमें से किसी में भी विशेषज्ञ नहीं हूं।
कोनराड रुडोल्फ

@ कोनराड, आवंटनकर्ता प्रकारों के बारे में दिलचस्प बिंदु और ऐसा कुछ नहीं जिसके बारे में मुझे पता था। जानकारी के लिए धन्यवाद।
स्मैकएल

11
std :: size_t आमतौर पर (हमेशा?) एक पॉइंटर का आकार होता है, न कि सबसे बड़े पूर्णांक के आकार का जो पूर्णांक गणित इकाई में देशी हार्डवेयर का समर्थन करता है। मेरे द्वारा उपयोग किए गए प्रत्येक x86 OS पर, size_t 32-बिट OS के लिए 32-बिट्स और 64-बिट OS के लिए 64-बिट्स है।
श्री फूज़

2
मेरी समझ यह है कि एक सरणी की अधिकतम सीमा प्रोसेसर के शब्द का अधिकतम मूल्य है । यह इंडेक्सिंग ऑपरेटर के कारण है। उदाहरण के लिए, एक मशीन में 16 बिट्स का शब्द आकार हो सकता है, लेकिन 32 बिट्स का एक एड्रेसिंग रजिस्टर। स्मृति का एक हिस्सा आकार में सीमित पैरामीटर द्वारा newया के पास है malloc। एक सरणी से बड़ा मेमोरी का एक हिस्सा पॉइंटर के माध्यम से पहुँचा जा सकता है।
थॉमस मैथ्यूज

171

स्टैक फ्रेम के आकार पर किसी ने सीमा का उल्लेख नहीं किया ।

दो जगहों पर मेमोरी आवंटित की जा सकती है:

  • हीप पर (गतिशील रूप से आवंटित मेमोरी)।
    यहाँ आकार सीमा उपलब्ध हार्डवेयर और OS की क्षमता का संयोजन है जो अन्य उपकरणों का उपयोग करके अंतरिक्ष का अनुकरण करने के लिए अस्थायी रूप से अप्रयुक्त डेटा ( यानी हार्ड डिस्क पर पृष्ठों को स्थानांतरित) करने के लिए उपयोग करता है।
  • स्टैक पर (स्थानीय रूप से घोषित चर)।
    यहां आकार की सीमा संकलक परिभाषित (संभव हार्डवेयर सीमाओं के साथ) है। यदि आप संकलक प्रलेखन को पढ़ते हैं तो आप अक्सर इस आकार को बदल सकते हैं।

इस प्रकार यदि आप एक सरणी को गतिशील रूप से आवंटित करते हैं (सीमा बड़ी है और अन्य पदों द्वारा विस्तार से वर्णित है।

int* a1 = new int[SIZE];  // SIZE limited only by OS/Hardware

वैकल्पिक रूप से यदि सरणी को स्टैक पर आवंटित किया जाता है तो आप स्टैक फ्रेम के आकार द्वारा सीमित होते हैं। एनबी वैक्टर और अन्य कंटेनरों की स्टैक में एक छोटी उपस्थिति है, लेकिन आमतौर पर डेटा का थोक ढेर पर होगा।

int a2[SIZE]; // SIZE limited by COMPILER to the size of the stack frame

4
बड़े सरणियों का पसंदीदा आवंटन स्टैक या विश्व स्तर पर परिभाषित नहीं है, बल्कि गतिशील आवंटन (के माध्यम से newया malloc) के माध्यम से है ।
थॉमस मैथ्यूज

1
@ थोमस मैथ्यूज: मेरी दुनिया में नहीं। गतिशील रूप से आवंटित वस्तुओं को प्रबंधन की आवश्यकता होती है। यदि इसे गतिशील रूप से आवंटित करने की आवश्यकता है, तो मैं एक स्टैक ऑब्जेक्ट का उपयोग करूंगा जो गतिशील रूप से आवंटित मेमोरी का प्रतिनिधित्व करता है, जैसे std :: वेक्टर।
मार्टिन यॉर्क

2
वहाँ एक कॉर्नर मामला गायब है: Global Arraysजबकि एक सौंदर्य और सबसे अच्छा नहीं बचा है, ये प्रतिबंध के तहत नहीं आते हैं stack, और आपको उनके साथ काम करने malloc/ freeकरने की आवश्यकता नहीं है।
टेड

1
@ क्यों, वैश्विक सरणियों को "सर्वश्रेष्ठ परहेज" क्यों किया जाना चाहिए? अधिक सटीक होने के लिए मुझे लगता है कि आप का अर्थ है सांख्यिकीय रूप से आवंटित सरणियाँ। उनका दायरा वैश्विक होना जरूरी नहीं है। मेरा तर्क है कि वे गतिशील सरणियों से बेहतर हैं क्योंकि आप उनके साथ पूर्ण पते (कम से कम लिनक्स पर) का उपयोग कर सकते हैं जो आप गतिशील रूप से आवंटित सरणियों के साथ नहीं कर सकते हैं।
Z बोसॉन

2
बहुत महत्वपूर्ण बिंदु। मैं हाल ही में एक "प्रोडक्शन-क्वालिटी" ओपन-सोर्स प्रोजेक्ट में आया था, जो एक कॉन्फ़िगर करने योग्य अधिकतम-बफर आकार प्रदान करता था। सभी बफ़र्स को स्टैक पर आवंटित किया गया था, इसलिए एक बड़े पर्याप्त मूल्य को कॉन्फ़िगर करने से प्रोग्राम तुरंत लॉन्च पर सेगफॉल्ट हो जाएगा।
एरोथ

13

सैद्धांतिक दृष्टिकोण के बजाय इसे व्यावहारिक रूप से देखने पर, 32 बिट विंडोज सिस्टम पर, एकल प्रक्रिया के लिए उपलब्ध मेमोरी की अधिकतम मात्रा 2 जीबी है। आप बहुत अधिक भौतिक मेमोरी के साथ 64 बिट ऑपरेटिंग सिस्टम पर जाकर सीमा को तोड़ सकते हैं, लेकिन यह करना है या विकल्प की तलाश करना आपके इच्छित उपयोगकर्ताओं और उनके बजट पर बहुत निर्भर करता है। आप पीएई का उपयोग करके इसे कुछ हद तक विस्तारित भी कर सकते हैं ।

सरणी का प्रकार बहुत महत्वपूर्ण है, क्योंकि कई कंपाइलरों पर डिफ़ॉल्ट संरचना संरेखण 8 बाइट्स है, जो कि स्मृति उपयोग एक समस्या है, तो बहुत बेकार है। यदि आप Windows को लक्षित करने के लिए Visual C ++ का उपयोग कर रहे हैं, तो इस पर काबू पाने के तरीके के रूप में #pragma पैक निर्देश देखें।

एक और बात यह है कि स्मृति संपीड़न तकनीकों में आपकी क्या मदद हो सकती है, जैसे कि विरल मैट्रिस, फ्लाई कम्प्रेशन, आदि ... फिर से यह अत्यधिक अनुप्रयोग पर निर्भर है। यदि आप अपने पोस्ट को संपादित करते हैं तो वास्तव में आपके सरणियों में क्या है, इसके बारे में अधिक जानकारी देने के लिए, आपको अधिक उपयोगी उत्तर मिल सकते हैं।

संपादित करें: आपकी सटीक आवश्यकताओं के बारे में थोड़ी और जानकारी देते हुए, आपके स्टोरेज की आवश्यकता 7.6 जीबी और 76 जीबी के बीच असम्पीडित दिखाई देती है, जिसे C ++ में मेमोरी के रूप में स्टोर करने के लिए एक महंगी 64 बिट बॉक्स की आवश्यकता होगी। यह प्रश्न उठाता है कि आप डेटा को मेमोरी में क्यों स्टोर करना चाहते हैं, जहां कोई एक्सेस की गति के लिए अनुमान लगाता है, और यादृच्छिक एक्सेस की अनुमति देता है। इस डेटा को किसी सरणी से बाहर संग्रहीत करने का सबसे अच्छा तरीका बहुत अधिक इस पर आधारित है कि आप इसे कैसे एक्सेस करना चाहते हैं। यदि आपको सरणी सदस्यों को यादृच्छिक रूप से एक्सेस करने की आवश्यकता है, तो अधिकांश अनुप्रयोगों के लिए डेटा के समूह क्लैंपिंग के तरीके होते हैं जो एक ही समय में एक्सेस करने की प्रवृत्ति रखते हैं। उदाहरण के लिए, बड़े जीआईएस और स्थानिक डेटाबेस में, डेटा अक्सर भौगोलिक क्षेत्र द्वारा टाइल किया जाता है। C ++ प्रोग्रामिंग शब्दों में, आप बाहरी डेटा से अपने डेटा के कुछ हिस्सों को लाने के लिए [] सरणी ऑपरेटर को ओवरराइड कर सकते हैं।


1
सिस्टम कॉल हैं जो प्रोग्राम स्पेस के बाहर मेमोरी के आवंटन की अनुमति देते हैं; लेकिन यह ओएस पर निर्भर है और पोर्टेबल नहीं है। हमने उन्हें एम्बेडेड सिस्टम में इस्तेमाल किया।
थॉमस मैथ्यूज

4

मैं ऊपर के साथ सहमत हूँ, कि अगर आप के साथ अपने सरणी intializing हैं

 int myArray[SIZE] 

तब SIZE एक पूर्णांक के आकार द्वारा सीमित होता है। लेकिन आप हमेशा मेमोरी का एक हिस्सा मॉलॉक कर सकते हैं और इसके पास एक पॉइंटर भी रख सकते हैं, जितना बड़ा आप उतने लंबे समय तक चाहते हैं, जब तक कि मॉलॉक फ्लॉप नॉट वापस नहीं आए।


मुझे यकीन नहीं है कि यह गलत है, या मैंने आपको गलत समझा, या कुछ और। उदाहरण के लिए, इसे MSVC17 कंपाइलर द्वारा रोका जाता है: int oops[INT_MAX]{0};यह उत्पन्न करता है,C2148 - total size of array must not exceed 0x7fffffff bytes
kayleeFrye_onDeck

16 जीबी DDR4 के साथ और 66%मेमोरी के बारे में वर्तमान में मेरे ऐप को VS2017 के साथ विंडोज 10 पर डिबग के रूप में लॉन्च करने से पहले उपयोग किया जाता है, मेरे पास एक अपरिभाषित सीमा है कि मैं कितने बड़े इंट-सरणी के साथ आरंभ कर सकता हूं 0। कभी-कभी मैं इसे ~ 257k तत्वों के साथ कर सकता हूं, कभी-कभी मुझे स्टैक ओवरफ्लो मिलता है। यदि मैं मुख्य और सरणी के अलावा अपने ऐप में कुछ भी जोड़ता हूं, तो वह संख्या नीचे (स्पष्ट रूप से) जाती है। मुझे इस संख्या को निर्धारित करने के लिए प्रयोग करना था, इसलिए मैं यह नहीं देखता कि वैक्यूम में आपकी सैद्धांतिक सीमाओं को जानने से परे इस मीट्रिक पर कैसे भरोसा किया जा सकता है।
kayleeFrye_onDeck

4

प्रतिक्रियाओं को सारांशित करने के लिए, उन्हें विस्तारित करें, और सीधे अपने प्रश्न का उत्तर देने के लिए:

नहीं, C ++ किसी सरणी के आयामों के लिए कोई सीमा नहीं लगाता है ।

लेकिन जैसा कि सरणी को मेमोरी में कहीं संग्रहीत किया जाना है, इसलिए कंप्यूटर सिस्टम के अन्य भागों द्वारा लगाए गए मेमोरी-संबंधित सीमाएं लागू होती हैं। ध्यान दें कि ये सीमाएं सीधे सरणी के आयाम (= तत्वों की संख्या) से संबंधित नहीं हैं , बल्कि इसके आकार (= ली गई स्मृति की मात्रा) से संबंधित हैं। किसी सरणी के आयाम ( D ) और इन-मेमोरी साइज़ ( S ) समान नहीं हैं, क्योंकि वे किसी एक तत्व ( E ): S = D * E द्वारा ली गई मेमोरी से संबंधित हैं ।

अभीई पर निर्भर करता है:

  • सरणी तत्वों का प्रकार (तत्व छोटे या बड़े हो सकते हैं)
  • स्मृति संरेखण (प्रदर्शन को बढ़ाने के लिए, तत्वों को उन पतों पर रखा जाता है जो कुछ मूल्य के गुणक होते हैं, जो
    तत्वों के बीच 'व्यर्थ स्थान' (पैडिंग) का परिचय देते हैं
  • वस्तुओं के स्थिर भागों का आकार (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग में उसी प्रकार की वस्तुओं के स्थिर घटकों को केवल एक बार संग्रहीत किया जाता है, इस तरह की समान वस्तुओं की संख्या से स्वतंत्र)

यह भी ध्यान दें कि आप आम तौर पर स्टैक पर सरणी डेटा आवंटित करके (एक स्वचालित चर के रूप में int t[N]) : या हीप पर ( एसटीएल तंत्र के साथ malloc()( newया साथ एसएलएल का उपयोग कर गतिशील ), या प्रक्रिया मेमोरी के स्थिर भाग में अलग-अलग मेमोरी-संबंधित सीमाएं प्राप्त करते हैं। एक स्थिर चर:) static int t[N]। यहां तक ​​कि जब ढेर पर आवंटित किया जाता है, तब भी आपको मेमोरी के ढेर-आवंटित ब्लॉकों के संदर्भों को संग्रहीत करने के लिए स्टैक पर कुछ छोटी मात्रा में मेमोरी की आवश्यकता होती है (लेकिन यह नगण्य है, आमतौर पर)। प्रकार के

आकार का size_tप्रोग्रामर पर कोई प्रभाव नहीं पड़ता है (मेरा मानना ​​है कि प्रोग्रामर size_tअनुक्रमण के लिए प्रकार का उपयोग करता है , जैसा कि इसके लिए डिज़ाइन किया गया है), क्योंकि संकलक प्रदाता को typedefपूर्णांक प्रकार के लिए यह बड़ा होता है कि दिए गए प्लेटफ़ॉर्म के लिए अधिकतम संभव अधिकतम मेमोरी को संबोधित कर सके। आर्किटेक्चर।

स्मृति-आकार की सीमाओं के स्रोत से स्टेम

  • प्रक्रिया के लिए उपलब्ध मेमोरी की मात्रा (जो 32-बिट अनुप्रयोगों के लिए 2 ^ 32 बाइट्स तक सीमित है, यहां तक ​​कि 64-बिट ओएस केल्स पर भी),
  • प्रक्रिया मेमोरी का विभाजन (जैसे स्टैक या हीप के लिए डिज़ाइन की गई मेमोरी की मात्रा),
  • भौतिक स्मृति का विखंडन (कई बिखरी हुई छोटी मुक्त स्मृति टुकड़े एक अखंड संरचना के भंडारण के लिए लागू नहीं होते हैं),
  • भौतिक स्मृति की मात्रा,
  • और वर्चुअल मेमोरी की मात्रा।

उन्हें आवेदन स्तर पर 'ट्वीक' नहीं किया जा सकता है, लेकिन आप एक अलग संकलक (स्टैक आकार सीमा को बदलने के लिए) का उपयोग करने के लिए स्वतंत्र हैं, या अपने आवेदन को 64-बिट में पोर्ट कर सकते हैं, या इसे दूसरे ओएस पर पोर्ट कर सकते हैं, या भौतिक / बदल सकते हैं वर्चुअल (वर्चुअल? भौतिक?) मशीन की वर्चुअल मेमोरी कॉन्फ़िगरेशन।

उपरोक्त सभी कारकों को बाहरी गड़बड़ी और इस प्रकार रनटाइम त्रुटियों के संभावित स्रोतों के रूप में व्यवहार करना, और अपने प्रोग्राम कोड में मेमोरी-आवंटन संबंधी त्रुटियों की सावधानीपूर्वक जांच और प्रतिक्रिया करना असामान्य (और यहां तक ​​कि उचित) नहीं है।

तो अंत में: जबकि C ++ किसी भी सीमा को लागू नहीं करता है, फिर भी आपको अपना कोड चलाते समय प्रतिकूल मेमोरी से संबंधित स्थितियों की जांच करनी होगी। :-)


3

जैसा कि कई उत्कृष्ट उत्तरों में उल्लेख किया गया है, बहुत सी सीमाएँ हैं जो आपके C ++ कंपाइलर, ऑपरेटिंग सिस्टम और कंप्यूटर विशेषताओं के संस्करण पर निर्भर करती हैं। हालांकि, मैं पायथन पर निम्नलिखित स्क्रिप्ट का सुझाव देता हूं जो आपकी मशीन पर सीमा की जांच करता है।

यह द्विआधारी खोज का उपयोग करता है और प्रत्येक पुनरावृत्ति जांच पर यदि मध्य आकार एक कोड बनाकर संभव है जो आकार की एक सरणी बनाने का प्रयास करता है। स्क्रिप्ट इसे संकलित करने का प्रयास करती है (क्षमा करें, यह हिस्सा केवल लिनक्स पर काम करता है) और सफलता के आधार पर द्विआधारी खोज को समायोजित करता है। इसकी जांच - पड़ताल करें:

import os

cpp_source = 'int a[{}]; int main() {{ return 0; }}'

def check_if_array_size_compiles(size):
        #  Write to file 1.cpp
        f = open(name='1.cpp', mode='w')
        f.write(cpp_source.format(m))
        f.close()
        #  Attempt to compile
        os.system('g++ 1.cpp 2> errors')
        #  Read the errors files
        errors = open('errors', 'r').read()
        #  Return if there is no errors
        return len(errors) == 0

#  Make a binary search. Try to create array with size m and
#  adjust the r and l border depending on wheather we succeeded
#  or not
l = 0
r = 10 ** 50
while r - l > 1:
        m = (r + l) // 2
        if check_if_array_size_compiles(m):
                l = m
        else:
                r = m

answer = l + check_if_array_size_compiles(r)
print '{} is the maximum avaliable length'.format(answer)

आप इसे अपनी मशीन में सहेज सकते हैं और लॉन्च कर सकते हैं, और यह आपके द्वारा बनाए गए अधिकतम आकार को प्रिंट कर देगा। मेरी मशीन के लिए यह 2305843009213693951 है।


2

एक बात जो मुझे नहीं लगती, वह पिछले उत्तरों में बताई गई है।

मैं हमेशा रिफ्लेक्टिंग अर्थों में "बुरी गंध" महसूस कर रहा हूं, जब लोग अपने डिजाइन में ऐसी चीजों का उपयोग कर रहे हैं।

यह एक विशाल सरणी है और संभवतः दक्षता के दृष्टिकोण और प्रदर्शन के दृष्टिकोण से अपने डेटा का प्रतिनिधित्व करने का सबसे अच्छा तरीका नहीं है।

चियर्स,

लूटना


क्या आपके पास कोई सुझाव है कि मुझे क्या उपयोग करना चाहिए?
लूइस

यदि आप हमें बता सकते हैं कि डेटा क्या है जो आप स्टोर कर रहे हैं तो शायद हम कर सकते हैं। (-:
रोब वेल्स

सॉरी लुइस मेरी पहली प्रतिक्रिया बहुत चपल थी। यह आपके डेटा की प्रकृति से प्रेरित होगा। आपके डेटा के रिलेशनशिप्स उस मॉडल को चलाएंगे जो आप डेटा का प्रतिनिधित्व करने के लिए उपयोग करते हैं। फिर संग्रह उसी से स्पष्ट होना चाहिए । यदि नहीं, तो मुझे डेटा मॉडल के बारे में चिंता होगी।
रॉब वेल्स

मेरे लिए ऐसा नहीं है: इस तरह से एक खिलौने के साथ एक कैश्ड डेटाबेस के बारे में कैसे? tweaktown.com/news/22066/…

2

यदि आपको उस डेटा से निपटना है, तो आपको इसे प्रबंधनीय विखंडू में विभाजित करने की आवश्यकता होगी। यह सभी किसी भी छोटे कंप्यूटर पर मेमोरी में फिट नहीं होगा। आप शायद डिस्क से डेटा का एक हिस्सा लोड कर सकते हैं (जो भी उचित रूप से फिट बैठता है), अपनी गणना करें और उसमें परिवर्तन करें, इसे डिस्क पर संग्रहीत करें, फिर पूरा होने तक दोहराएं।


मेमोरी में फिट होने के लिए डेटा को संभालने के लिए एक उदाहरण एल्गोरिथ्म पर मर्ज सॉर्ट के लिए भी देखें।
थॉमस मैथ्यूज

2

जैसा कि सभी मौजूदा उत्तर हैं, गैर-विशिष्ट रूप से गैर-विशिष्ट हैं, वे ज्यादातर सही हैं, लेकिन कई चेतावनी के साथ, हमेशा उल्लेख नहीं किया जाता है। गिस्ट है, आपकी दो ऊपरी सीमाएँ हैं, और उनमें से केवल एक ही वास्तव में परिभाषित है, इसलिए YMMV :

1. संकलन-समय सीमा

मूल रूप से, आपका कंपाइलर क्या अनुमति देगा। दृश्य C ++ 2017 के लिए एक x64 विंडोज 10 बॉक्स पर, यह 2GB सीमा बढ़ाने से पहले संकलन-समय पर मेरी अधिकतम सीमा है,

unsigned __int64 max_ints[255999996]{0};

अगर मैंने इसके बजाय,

unsigned __int64 max_ints[255999997]{0};

मुझे मिलेगा:

Error C1126 automatic allocation exceeds 2G

मुझे यकीन नहीं है कि कैसे 2 जी correllates करने के लिए 255999996/ 7। मैंने दोनों नंबरों को नजरअंदाज कर दिया, और केवल एक चीज जिसे मैं पा सकता था, संभवतः यह संबंधित था * nix क्यू एंड ए के साथdc एक सटीक मुद्दे के बारे में । किसी भी तरह से, यह कोई फर्क नहीं पड़ता है कि आप किस प्रकार के इंट सरणी को भरने की कोशिश कर रहे हैं, बस कितने तत्वों को आवंटित किया जा सकता है।

2. रन-टाइम सीमा

आपके ढेर और ढेर की अपनी सीमाएँ हैं। ये सीमाएं दोनों मूल्य हैं जो उपलब्ध सिस्टम संसाधनों के आधार पर बदलते हैं, साथ ही साथ आपका ऐप कितना "भारी" है। उदाहरण के लिए, अपने मौजूदा सिस्टम संसाधनों के साथ, मैं इसे चलाने के लिए प्राप्त कर सकता हूं:

int main()
{
    int max_ints[257400]{ 0 };
    return 0;
}

लेकिन अगर मैं इसे सिर्फ एक छोटा सा tweak ...

int main()
{
    int max_ints[257500]{ 0 };
    return 0;
}

बैम! स्टैक ओवरफ़्लो!

Exception thrown at 0x00007FF7DC6B1B38 in memchk.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x000000AA8DE03000). Unhandled exception at 0x00007FF7DC6B1B38 in memchk.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x000000AA8DE03000).

और अपने ऐप पॉइंट के पूरे भारीपन को विस्तार देने के लिए, यह जाने के लिए अच्छा था:

int main()
{
    int maxish_ints[257000]{ 0 };
    int more_ints[400]{ 0 };
    return 0;
}  

लेकिन इससे स्टैक ओवरफ्लो हो गया:

int main()
{
    int maxish_ints[257000]{ 0 };
    int more_ints[500]{ 0 };
    return 0;
}  

1

मुझे आश्चर्य है कि std :: वेक्टर का max_size () सदस्य फ़ंक्शन यहाँ उल्लेख नहीं किया गया है।

"सिस्टम या लाइब्रेरी कार्यान्वयन सीमाओं के कारण कंटेनर की अधिकतम संख्या को रखने में सक्षम है, यानी सबसे बड़े कंटेनर के लिए std :: दूरी (शुरू (), अंत) (।)।"

हम जानते हैं कि std::vectorहुड के नीचे एक गतिशील सरणी के रूप में कार्यान्वित किया जाता है, इसलिए max_size()आपको अपनी मशीन पर एक गतिशील सरणी की अधिकतम लंबाई का एक बहुत करीब सन्निकटन देना चाहिए ।

निम्न प्रोग्राम विभिन्न डेटा प्रकारों के लिए अनुमानित अधिकतम सरणी लंबाई की तालिका बनाता है।

#include <iostream>
#include <vector>
#include <string>
#include <limits>

template <typename T>
std::string mx(T e) {
    std::vector<T> v;
    return std::to_string(v.max_size());
}

std::size_t maxColWidth(std::vector<std::string> v) {
    std::size_t maxWidth = 0;

    for (const auto &s: v)
        if (s.length() > maxWidth)
            maxWidth = s.length();

    // Add 2 for space on each side
    return maxWidth + 2;
}

constexpr long double maxStdSize_t = std::numeric_limits<std::size_t>::max();

// cs stands for compared to std::size_t
template <typename T>
std::string cs(T e) {
    std::vector<T> v;
    long double maxSize = v.max_size();
    long double quotient = maxStdSize_t / maxSize;
    return std::to_string(quotient);
}

int main() {
    bool v0 = 0;
    char v1 = 0;

    int8_t v2 = 0;
    int16_t v3 = 0;
    int32_t v4 = 0;
    int64_t v5 = 0;

    uint8_t v6 = 0;
    uint16_t v7 = 0;
    uint32_t v8 = 0;
    uint64_t v9 = 0;

    std::size_t v10 = 0;
    double v11 = 0;
    long double v12 = 0;

    std::vector<std::string> types = {"data types", "bool", "char", "int8_t", "int16_t",
                                      "int32_t", "int64_t", "uint8_t", "uint16_t",
                                      "uint32_t", "uint64_t", "size_t", "double",
                                      "long double"};

    std::vector<std::string> sizes = {"approx max array length", mx(v0), mx(v1), mx(v2),
                                      mx(v3), mx(v4), mx(v5), mx(v6), mx(v7), mx(v8),
                                      mx(v9), mx(v10), mx(v11), mx(v12)};

    std::vector<std::string> quotients = {"max std::size_t / max array size", cs(v0),
                                          cs(v1), cs(v2), cs(v3), cs(v4), cs(v5), cs(v6),
                                          cs(v7), cs(v8), cs(v9), cs(v10), cs(v11), cs(v12)};

    std::size_t max1 = maxColWidth(types);
    std::size_t max2 = maxColWidth(sizes);
    std::size_t max3 = maxColWidth(quotients);

    for (std::size_t i = 0; i < types.size(); ++i) {
        while (types[i].length() < (max1 - 1)) {
            types[i] = " " + types[i];
        }

        types[i] += " ";

        for  (int j = 0; sizes[i].length() < max2; ++j)
            sizes[i] = (j % 2 == 0) ? " " + sizes[i] : sizes[i] + " ";

        for  (int j = 0; quotients[i].length() < max3; ++j)
            quotients[i] = (j % 2 == 0) ? " " + quotients[i] : quotients[i] + " ";

        std::cout << "|" << types[i] << "|" << sizes[i] << "|" << quotients[i] << "|\n";
    }

    std::cout << std::endl;

    std::cout << "N.B. max std::size_t is: " <<
        std::numeric_limits<std::size_t>::max() << std::endl;

    return 0;
}

मेरे macOS पर (क्लेंग संस्करण 5.0.1), मुझे निम्नलिखित मिलेंगे:

|  data types | approx max array length | max std::size_t / max array size |
|        bool |   9223372036854775807   |             2.000000             |
|        char |   9223372036854775807   |             2.000000             |
|      int8_t |   9223372036854775807   |             2.000000             |
|     int16_t |   9223372036854775807   |             2.000000             |
|     int32_t |   4611686018427387903   |             4.000000             |
|     int64_t |   2305843009213693951   |             8.000000             |
|     uint8_t |   9223372036854775807   |             2.000000             |
|    uint16_t |   9223372036854775807   |             2.000000             |
|    uint32_t |   4611686018427387903   |             4.000000             |
|    uint64_t |   2305843009213693951   |             8.000000             |
|      size_t |   2305843009213693951   |             8.000000             |
|      double |   2305843009213693951   |             8.000000             |
| long double |   1152921504606846975   |             16.000000            |

N.B. max std::size_t is: 18446744073709551615

पर ideone जीसीसी 8.3 मैं मिलता है:

|  data types | approx max array length | max std::size_t / max array size |
|        bool |   9223372036854775744   |             2.000000             |
|        char |   18446744073709551615  |             1.000000             |
|      int8_t |   18446744073709551615  |             1.000000             |
|     int16_t |   9223372036854775807   |             2.000000             |
|     int32_t |   4611686018427387903   |             4.000000             |
|     int64_t |   2305843009213693951   |             8.000000             |
|     uint8_t |   18446744073709551615  |             1.000000             |
|    uint16_t |   9223372036854775807   |             2.000000             |
|    uint32_t |   4611686018427387903   |             4.000000             |
|    uint64_t |   2305843009213693951   |             8.000000             |
|      size_t |   2305843009213693951   |             8.000000             |
|      double |   2305843009213693951   |             8.000000             |
| long double |   1152921504606846975   |             16.000000            |

N.B. max std::size_t is: 18446744073709551615

यह ध्यान दिया जाना चाहिए कि यह एक सैद्धांतिक सीमा है और अधिकांश कंप्यूटरों पर, आप इस सीमा तक पहुंचने से पहले ही स्मृति से बाहर चले जाएंगे। उदाहरण के लिए, हम देखते हैं कि प्रकार के लिए charपर gcc, तत्वों की अधिकतम संख्या की अधिकतम के बराबर है std::size_tयह प्रयास करते हुए , हमें त्रुटि मिलती है:

prog.cpp: In function int main()’:
prog.cpp:5:61: error: size of array is too large
  char* a1 = new char[std::numeric_limits<std::size_t>::max()];

अंत में, जैसा कि @MartinYork बताता है, स्थिर सरणियों के लिए अधिकतम आकार आपके स्टैक के आकार द्वारा सीमित है।


0

जैसा कि पहले ही बताया जा चुका है, सरणी का आकार आपके हार्डवेयर और आपके OS (मैन अलिमिट) द्वारा सीमित है। आपका सॉफ़्टवेयर यद्यपि, केवल आपकी रचनात्मकता द्वारा सीमित हो सकता है। उदाहरण के लिए, क्या आप डिस्क पर अपना "एरे" स्टोर कर सकते हैं? क्या आपको वास्तव में लंबे लंबे ints की आवश्यकता है? क्या आपको वास्तव में घने सरणी की आवश्यकता है? क्या आपको भी एक सरणी की आवश्यकता है?

एक सरल समाधान 64 बिट लिनक्स का उपयोग करना होगा। यहां तक ​​कि अगर आप शारीरिक रूप से आपके सरणी के लिए पर्याप्त राम नहीं हैं, तो ओएस आपको स्मृति आवंटित करने की अनुमति देगा जैसे कि आप करते हैं क्योंकि आपकी प्रक्रिया के लिए उपलब्ध वर्चुअल मेमोरी भौतिक मेमोरी की तुलना में बहुत बड़ी है। यदि आपको वास्तव में सरणी में सब कुछ एक्सेस करने की आवश्यकता है, तो यह इसे डिस्क पर संग्रहीत करने के लिए है। आपके एक्सेस पैटर्न के आधार पर, ऐसा करने के और अधिक कुशल तरीके हो सकते हैं (जैसे: mmap () का उपयोग करना, या बस किसी फ़ाइल में क्रमिक रूप से डेटा संग्रहीत करना (जिस स्थिति में 32 बिट लिनक्स पर्याप्त होगा))।


2
हम्म, डिस्क, arrays, ... किसी को भी आभासी स्मृति के बारे में सुना है । वर्चुअल मेमोरी का समर्थन करने वाले OS मेमोरी के लिए बाहरी डिवाइस का उपयोग करना शुरू कर देंगे, जैसे कि हार्ड डिस्क, और आंतरिक मेमोरी के साथ विखंडू को स्वैप करना।
थॉमस मैथ्यूज

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