2011-12-23 14 views
6

क्रैशिंग मैं केवल & आर पढ़ने के बारे में हूं, और यह सब सी है जो मुझे पता है। मेरा सभी संकलन मिनीजीडब्लू का उपयोग कर विंडोज कमांड लाइन से किया गया है, और मुझे उन्नत डिबगिंग विधियों का कोई ज्ञान नहीं है (इसलिए नीचे मेरे दूसरे कार्यक्रम में "यहूदी डेबग" टिप्पणी है)।मेमोरी आवंटन को समझना, परीक्षण प्रोग्राम

मैं कुछ छोटे परीक्षण कार्यक्रम बनाने की कोशिश कर रहा हूं ताकि मुझे यह समझने में मदद मिल सके कि स्मृति आवंटन कैसे काम करता है। ये पहले जोड़े कार्यक्रम मॉलोक या फ्री का उपयोग नहीं करते हैं, मैं सिर्फ यह देखना चाहता था कि स्मृति को आवंटित किया जाता है और फ़ंक्शन के लिए स्थानीय मानक एरे के लिए आवंटित किया जाता है। विचार यह है कि मैं अपनी चल रही प्रक्रियाओं को राम उपयोग देखने के लिए देखता हूं यह देखने के लिए कि क्या मैं समझता हूं। नीचे दिए गए पहले कार्यक्रम के लिए, यह काम करता है जैसा कि मैंने उम्मीद की थी। alloc_one_meg() फ़ंक्शन आवंटित करता है और 250,000 4-बाइट पूर्णांक प्रारंभ करता है, लेकिन जैसे ही फ़ंक्शन लौटाता है, उस एमबी को आवंटित किया जाता है। तो अगर मैं लगातार 1000000 बार उस समारोह को कॉल करता हूं, तो मुझे कभी भी अपना रैम उपयोग 1 एमबी से ऊपर नहीं देखना चाहिए। और, यह काम करता है।

#include <stdio.h> 
#include <stdlib.h> 

void alloc_one_meg() { 
    int megabyte[250000]; 
    int i; 
    for (i=0; i<250000; i++) { 
     megabyte[i] = rand(); 
    } 
} 

main() 
{ 
    int i; 
    for (i=0; i<1000000; i++) { 
     alloc_one_meg(); 
    } 
} 

नीचे इस दूसरे कार्यक्रम के लिए, विचार एक ही बार में एक ही समारोह चल रहा है के 1000 प्रतिलिपियां, जो मैं प्रत्यावर्तन के साथ पूरा किया समारोह से बाहर निकलने की अनुमति नहीं करने के लिए किया गया था। मेरा सिद्धांत यह था कि कार्यक्रम 1 जीबी रैम का उपभोग करेगा इससे पहले कि इसे रिकर्सन समाप्त होने के बाद इसे आवंटित किया जाए। हालांकि, यह रिकर्सन के माध्यम से दूसरे लूप से पहले नहीं मिलता है (मेरी यहूदी डीबग टिप्पणी देखें)। कार्यक्रम एक सुंदर गैर-सूचनात्मक (मेरे लिए) संदेश के साथ दुर्घटनाग्रस्त हो जाता है (एक विंडोज पॉप-अप कह रहा है ____। Exe में कोई समस्या आई है)। आम तौर पर मैं हमेशा अपने यहूदी डेबग विधि के साथ चीजों के नीचे पहुंच सकता हूं ... लेकिन यह यहां काम नहीं कर रहा है। मैं उलझन में हूं। इस कोड के साथ समस्या क्या है? धन्यवाद!

#include <stdio.h> 
#include <stdlib.h> 

int j=0; 

void alloc_one_meg() { 
    int megabyte[250000]; 
    int i; 
    for (i=0; i<250000; i++) { 
     megabyte[i] = rand(); 
    } 
    j++; 
    printf("Loop %d\n", j); // ghetto debug 
    if (j<1000) { 
     alloc_one_meg(); 
    } 
} 

main() 
{ 
    alloc_one_meg(); 
} 

अनुवर्ती प्रश्न here पोस्ट किया गया।

+2

और अब जब आपके पास एक स्टैक ओवरफ़्लो क्रैश है, तो आपके पास स्मृति की एक बेहतर समझ है। मजेदार है कि चीजें इस तरह कैसे काम करती हैं। –

+2

हाँ, मैं प्रोग्रामिंग के लिए नया हूं, लेकिन परीक्षण के विचार के लिए नया नहीं हूं। मैं एक इंजीनियर और एक भारी सॉफ्टवेयर यूजर हूं, और मुझे अच्छी तरह पता है कि चीजों को तोड़ने का सबसे अच्छा तरीका है! :-) – The111

उत्तर

3

आप एक स्टैक ओवरफ़्लो में चल रहे हैं।

स्थानीय स्वचालित स्टोरेज चर (जैसे megabyte) स्टैक पर आवंटित किए जाते हैं, जिसमें सीमित मात्रा में स्थान होता है। मॉलोक ढेर पर आवंटित करता है, जो बहुत अधिक आवंटन की अनुमति देता है।

आप यहाँ और अधिक पढ़ सकते हैं:

http://en.wikipedia.org/wiki/Stack_overflow

(मैं नोट करना चाहिए सी भाषा निर्दिष्ट करें कि यह नहीं है कि जहां स्मृति आवंटित किया जाता है - ढेर और ढेर कार्यान्वयन विवरण दिए गए हैं)

+4

कितना अच्छा, मैंने stackoverflow.com पर स्टैक ओवरफ़्लो के बारे में सीखा। मुझे इसे मेटा पर पोस्ट करना चाहिए! स्पष्टीकरण और लिंक के लिए धन्यवाद। – The111

+0

malloc() में बड़ी मात्रा में स्थान नहीं है - डंपबिन से आउटपुट देखें और "ढेर" के लिए आरक्षित राशि देखें। –

2

का आकार विंडोज प्रोग्राम में ढेर आमतौर पर लगभग 1 एमबी होता है, इसलिए दूसरे रिकर्सन पर, आप ढेर से बह रहे हैं।

void alloc_one_meg() { 
    int *megabyte = malloc(sizeof(int) * 250000); // allocate space for 250000 
                // ints on the heap 
    int i; 
    for (i=0; i<250000; i++) { 
     megabyte[i] = rand(); 
    } 
    j++; 
    printf("Loop %d\n", j); // ghetto debug 
    if (j<1000) { 
     alloc_one_meg(); 
    } 

    free(megabyte); // DO NOT FORGET THIS 
} 

कहा: आप ढेर पर इतनी बड़ी सरणियों का आवंटन नहीं किया जाना चाहिए, malloc और free का उपयोग आवंटित और ढेर पर स्मृति पुनःआवंटन करने के लिए (कोई रास्ता नहीं सरणियों के इस तरह के आकार के लिए चारों ओर malloc प्राप्त करने के लिए है) , आप वास्तव में एक कार्यक्रम के ढेर आकार को बदल सकते हैं और इसे बड़ा बना सकते हैं (हालांकि मैं केवल एक शैक्षणिक अभ्यास के रूप में ऐसा करता हूं, उत्पादन कोड में नहीं)। विजुअल स्टूडियो के लिए आप use the /F compiler option कर सकते हैं, और लिनक्स पर आप setrlimit(3) का उपयोग कर सकते हैं। मुझे यकीन नहीं है कि मिनजीडब्ल्यू के साथ क्या उपयोग करना है।

+0

उन्होंने कहा कि वह मॉलोक/मुफ्त का उपयोग नहीं करना चाहता था। – Pubby

+2

@ पब्बी वह उनका उपयोग नहीं कर सकता –

+0

परीक्षणों की इस श्रृंखला के बड़े उद्देश्य का हिस्सा मुझे मॉलोक और मुफ्त के उद्देश्य को समझने में मदद करना था। मैं उनके बिना पहले कुछ परीक्षण करना चाहता था, फिर उनके साथ कुछ परीक्षण। मुझे पता था कि स्थानीय स्टैक वैरिएबल में फ़ंक्शन एंटर/एक्जिट से संबंधित जीवन था, जबकि ढेर चर के पास मॉलोक/फ्री से संबंधित जीवन था, लेकिन मुझे नहीं पता था कि ढेर की इतनी छोटी सीमा थी। तो मैंने इस परीक्षा के साथ पहले से ही एक बड़ी बात सीखी है। :-) – The111

0

स्टैक ओवरव्लो। क्या यह एक चाल सवाल है?

+0

नहीं, मैं सिर्फ एक नोब हूं। मैं बहुत जल्दी सीख रहा हूं कि सी के बारे में बहुत कुछ है जो मुझे यह जानने की जरूरत है कि मैं के एंड आर से नहीं प्राप्त कर सकता (जैसा कि मैंने कहा, अब तक मेरा ज्ञान का एकमात्र स्रोत)।ज्ञान के बारे में जानने के लिए एक अच्छी जगह कहां है जो मुझे ऐसे प्रश्न पूछने से रोकती? ढेर/ढेर, उस तरह की चीज (उन अवधारणाओं के एंड आर में मौजूद नहीं हैं, और मुझे एहसास है क्यों)। – The111

1

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

dumpbin उपयोगिता का उपयोग करना, दृश्य स्टूडियो के साथ शामिल ही (dumpbin.exe) के साथ इनपुट फ़ाइल के रूप में:

 100000 size of stack reserve 
     2000 size of stack commit 

:

dumpbin /headers dumpbin.exe

... वहाँ कुछ उत्पादन, और उसके बाद है "100000" एक हेक्साडेसिमल संख्या 1,048,576 के बराबर है, इसलिए यह लगभग 1 एमबी का प्रतिनिधित्व करता है।

दूसरे शब्दों में, ऑपरेटिंग सिस्टम केवल स्टैक के लिए 1 एमबी पता श्रेणी आरक्षित करेगा। जब उस एड्रेस रेंज का उपयोग किया जाता है, तो विंडोज स्टैक को बढ़ाने के लिए लगातार मेमोरी रेंज आवंटित करने में सक्षम हो सकता है या नहीं। परिणाम इस बात पर निर्भर करता है कि आगे संगत पता सीमा उपलब्ध है या नहीं। थ्रेड शुरू होने पर किए गए अन्य आवंटन के कारण, यह उपलब्ध होने की संभावना बहुत कम है।

विंडोज के तहत अधिकतम वर्चुअल मेमोरी आवंटित करने के लिए, VirtualAlloc फ़ंक्शन के परिवार का उपयोग करें।

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