2011-03-10 10 views
7

मेरे पास एक जीयूआई एप्लीकेशन है जो मेमोरी रिसाव नहीं है। मैंने कई परीक्षण चक्रों पर फास्टएमएम के साथ इसकी पुष्टि की है। एक विशेष ग्राहक के सर्वर पर, मुझे यादृच्छिक दुर्घटनाएं मिलती हैं। सर्वर चश्मे हमारे अन्य ग्राहकों के साथ अच्छी तरह से हैं (और हमने वास्तव में विभिन्न हार्डवेयर पर कोशिश की है), और इस तरह प्रोग्राम द्वारा उपयोग की जाने वाली फाइलें हैं (जहां तक ​​मैं कह सकता हूं, कुछ सुपर-संवेदनशील सामग्री है I तक पहुंच नहीं मिल सकती है, लेकिन वहां सामान्य से कुछ भी नहीं लगता है)।डेल्फी - जांचें कि "समय पर" स्मृति जारी की जा रही है

मैंने इस मुद्दे को कम करने के लिए यूरेकालोग और माधी की पसंद की कोशिश की है, लेकिन दुर्भाग्यवश, वे केवल अवसर पर दुर्घटना के समय अपवाद पकड़ते हैं, हर समय नहीं। जब ऐसा होता है, तो यह आमतौर पर दुर्घटना से पहले एक या अधिक "स्मृति से बाहर" त्रुटि दिखाता है।

तो मैं सोच रहा हूं कि कुछ वस्तुएं "बहुत देर हो चुकी हैं", यानी जब एप्लिकेशन बंद हो रहा है, तो जब मैं उन्हें मुक्त करना चाहता हूं तो इसका विरोध किया जाता है? मैंने FastMMUsageeTracker डेमो देखा है, लेकिन वास्तव में यह सब समझ में नहीं आया। क्या कहीं भी दस्तावेज है? या कोई व्यक्ति (कुछ हद तक सुलभ) शब्दों में डाल सकता है कि मैं इसके बारे में कैसे जांच सकता हूं?

वैकल्पिक रूप से, यह पता लगाने का सबसे अच्छा तरीका क्या होगा कि एप्लिकेशन इसकी "स्मृति सीमा" के करीब आ रहा है, ताकि कुछ निवारक कार्रवाई कर सकें? अगर मैं सही ढंग से समझता हूं, नियमित डेल्फी ऐप 32 बिट है, तो यह 2 जीबी मेमोरी तक ठीक से संभालना चाहिए (बशर्ते हार्डवेयर इसे निश्चित रूप से समर्थन देता है), सही?

पुनश्च: डेल्फी 2009 या XE, जो अगर प्रासंगिक है

धन्यवाद!

संपादित करें - अंक संभवतः

हल हम एक ऐसी समस्या खोजने में सफल रहे हैं, जहां एक पॉप-अप विंडो कि बंद कर देता है और स्वयं को अपने आप को मुक्त कर देते कुछ समय बाद एक बहुत तेज दर से बनाया जा रहा था की तुलना में यह गायब हो गया था। यह समय के साथ बड़ी मात्रा में स्मृति खाएगा, और उसके बाद कोई स्मृति आवंटन मूल रूप से किनारे पर लाएगा और "स्मृति से बाहर" समस्या को ट्रिगर करेगा।

यह समझाएगा कि स्टैक निशान जहां असंगत है।

मुझे पूरी तरह से आश्वस्त नहीं है कि यह हमारा एकमात्र मुद्दा है, भले ही यह संभावना न हो कि यह परिदृश्य हमारे आवेदन चल रहे वर्षों से पहले हो सकता है, लेकिन किसी भी तरह से यह नहीं है। मैं इस मुद्दे पर बहुत अधिक खुदाई करूँगा।

उन सभी के लिए धन्यवाद जिन्होंने जवाब दिया, प्रत्येक जवाब में वास्तव में इसकी मूल्यवान जानकारी है।

+1

पीएस मेमोरी अपवादों से बाहर लगभग 1 जीबी ऊपर से कहीं भी हो सकता है - कोई पूर्व परिभाषित स्तर नहीं है। ऐसे कई कारक हैं जो सटीक सीमा को प्रभावित करते हैं: कुल रैम, कुल वर्चुअल मेमोरी, अन्य प्रक्रियाओं द्वारा कितना उपयोग किया जा रहा है आदि। इसके अलावा, नीचे मेरा कोड मूल रूप से फास्टएमएम मेमोरी ट्रैकर से है! – Misha

+1

ध्यान देने योग्य एक बात: मैंने कभी भी उन परियोजनाओं में उपलब्ध स्मृति को समाप्त करने में कामयाब नहीं रहा है जिन पर मैंने काम किया है, लेकिन मुझे कुछ बार स्मृति त्रुटियों से बाहर निकला है। यह कुछ मामलों में दूषित या बुरी तरह से गणना किए गए डेटा द्वारा स्मृति प्रबंधक से आकार में कुछ गीगाबाइट्स के एक बफर को आवंटित करने के लिए कहने का प्रयास कर सकता है, जब आपको वास्तव में कुछ की आवश्यकता होती है तो कुछ कम या कम होता है। –

उत्तर

7

यदि आपके पास डेल्फी एक्सई है, तो यह एकटाइम के साथ आता है, और एकटाइम में अपने चाल के बैग के हिस्से के रूप में स्मृति आवंटन प्रोफाइलर होता है। यदि आप इसे अपने प्रोग्राम पर चलाते हैं तो आप देख सकते हैं कि आपकी रैम कहां जा रही है।

+1

धन्यवाद मेसन। मैंने कोशिश की (मुझे इसके लिए बड़ी उम्मीद थी), और मैंने प्रो संस्करण के परीक्षण की भी कोशिश की। किसी कारण से, मुझे काम करने के लिए आवंटन प्रोफाइलर नहीं मिल रहा है। इसके बजाय, जब मैं इसे परिणाम प्राप्त करने के लिए कहता हूं, तो मुझे लगता है कि मैंने इसे एक घंटे से अधिक समय तक "परिणाम प्राप्त करने" छोड़ा - ऐप के पास प्रासंगिक होने पर लगभग 100 एमबी का एक सेटिंग सेट था - और कभी नहीं "परिणाम प्राप्त करने का प्रयास" संदेश)। यह स्टैंडअलोन और एकीकृत दोनों संस्करणों के साथ समान है। मैं बिना किसी समस्या के प्रदर्शन करने के लिए प्रदर्शन प्रोफाइलर प्राप्त कर सकता हूं, लेकिन आवंटन नहीं। – Bourgui

+0

अद्यतन: मैंने स्टैंडअलोन समर्थक संस्करण का उपयोग करने में कामयाब रहा है - जब मैंने अपना एप्लिकेशन बनाया था, तो मैं स्टैक ट्रेस उत्पन्न करना भूल गया था, और अब मैं आवंटन प्रोफाइलर का उपयोग करने में सक्षम हूं। यह मुझे एक समय की पॉपअप विंडो की ओर इशारा करता है जिसे सैकड़ों या हजारों बार कहा जा रहा था, यह वास्तव में बंद होने के तथ्य से मुआवजा दिया जा सकता है। हालांकि आईडीई-एकीकृत संस्करण से परिणाम प्राप्त नहीं हो सकते हैं (???)। – Bourgui

+0

उत्तर के रूप में चिह्नित किया गया है, इस तरह से मुझे वास्तव में पॉप-अप समस्या मिली। – Bourgui

3

आप यह पता लगा सकते हैं कि आपका एप्लिकेशन कितना मेमोरी उपयोग कर रहा है - यह About पृष्ठ देखें। सारांश:

uses PsAPI; 

//current memory size of the current process in bytes 
function CurrentMemoryUsage: Cardinal; 
var 
    pmc: TProcessMemoryCounters; 
begin 
    pmc.cb := SizeOf(pmc) ; 
    if GetProcessMemoryInfo(GetCurrentProcess, @pmc, SizeOf(pmc)) then 
    Result := pmc.WorkingSetSize 
    else 
    RaiseLastOSError; 
end; 
ShowMessage(FormatFloat('Memory used: ,.# K', CurrentMemoryUsage/1024)) ; 

यदि आप समय-समय पर अपने सर्वर में उस मान को लॉग करते हैं तो आपको कम से कम क्या हो रहा है इसका एक अनुमान प्राप्त होगा। उस परिणाम में और जानकारी है जो आपको यह जानने में मदद करनी चाहिए कि आपका प्रोग्राम क्या कर रहा है।

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

फास्टएमएम के पूर्ण संस्करण पर/3 जीबी स्विच का उपयोग करना संभव है और देखें कि समस्या होने में अधिक समय लगता है या नहीं।

यदि आप शानदार रूप से दुर्भाग्यपूर्ण हैं तो आप फास्टएमएम के मेमोरी पूल प्रबंधन एल्गोरिदम को "टूटा" करेंगे, इसलिए यह कभी भी स्मृति (a related question) जारी नहीं करेगा। अलग-अलग मेमोरी मैनेजर की कोशिश करने से आप मदद कर सकते हैं कि कुछ अप्रयुक्त स्मृति को पुनः प्राप्त करने के बारे में अधिक आक्रामक हैं। लेकिन अगर आप अपने ढेर को तोड़ रहे हैं तो एकमात्र वास्तविक समाधान यह है कि इसे करने से बचें। जो एक जटिल विषय है, फिर से: पहले ऊपर की सरल चीजों को आजमाएं।

+0

धन्यवाद मोज़ा। मैंने TProcessMemoryCounters के साथ काम करना शुरू कर दिया है, हालांकि, क्या यह "केवल" वर्क सेट मेमोरी, उर्फ ​​रैम मेमोरी में प्रदान नहीं करता है? बस अनुमान लगाया जा रहा है, लेकिन "स्मृति से बाहर" त्रुटि का सुझाव नहीं है कि यह समग्र वर्चुअल मेमोरी है जो बहुत बड़ी है? यदि मैं गलत हूं तो मुझे सही करों। मैं/3 जी स्विच आज़माउंगा। – Bourgui

+0

@ बौर्गुई, "स्मृति से बाहर" एक बहुत व्यापक संदेश है, और एक आधुनिक मशीन में 2 जीबी से अधिक भौतिक मेमोरी (अधिक) होनी चाहिए, इसलिए आपको वर्चुअल मेमोरी थकाऊ नहीं होनी चाहिए। ProcessMemoryCounters संरचना में अन्य जानकारी है, मैं पूरी तरह से लॉग इन करता हूं और देखता हूं कि क्या परिवर्तन हैं। लॉगिंग आपको यह भी मदद करने में मदद करेगी कि वास्तव में यह सब गलत कहां जाता है। मैं सुझाव देता हूं कि आपके अपवादों से स्टैक निशान भी देखें। सबसे खराब स्थिति में आपको बाहरी लॉगर लिखना पड़ सकता है यदि आपको लगता है कि आपकी लॉगिंग स्मृति स्थिति से बाहर हो जाती है। लेकिन जब तक आपको इसकी आवश्यकता न हो तब तक इससे बचें। प्रतिक्रिया के लिए –

+0

धन्यवाद। मैंने यही सोचा।दुर्भाग्य से मेरे ज्यादातर ढेर निशान मुझे कहीं भी नहीं ले जा रहे थे, और ज्यादातर असंगत थे। मैं तब से एक समस्या को अलग करने में सक्षम था (मेरा ओपी संपादन देखें) - उम्मीद है कि यह मेरे सभी मुद्दों का स्रोत है। – Bourgui

1

जब मुझे "स्मृति से बाहर" त्रुटि मिली है, तो यह एक भाग्यशाली लूप के कारण था। लूप आमतौर पर स्मृति आवंटित करेगा और सभी उपलब्ध स्मृति का उपयोग करने से पहले नहीं रुक जाएगा। स्मृति मुक्त करना कोई मुद्दा नहीं था, क्योंकि कार्यक्रम उस बिंदु पर कभी नहीं जाता था। कोड के प्रकार है कि मुझे काट लिया गया है:

एक एक "x.Next" डाटासेट के माध्यम से अग्रिम करने के लिए बिना पाश "जबकि x.Eof ऐसा नहीं", या

एक पुनरावर्ती प्रक्रिया या सबरूटीन कि सामना करना पड़ा कभी नहीं निकास की स्थिति (ओं)।

मैं किसी भी तरह की लूप या रिकर्सन की तलाश करता हूं जो कुछ परिस्थितियों में "हमेशा के लिए" जारी रख सकता है, जैसे मेमोरी में डेटा संरचना का निर्माण करना।

+0

धन्यवाद crefird, लेकिन मुझे नहीं लगता कि यह मामला यहां है। अब तक जो कुछ मिला है उस पर अधिक जानकारी के लिए मेरा संपादन देखें। – Bourgui

6

"विंडोज़" मेमोरी के बारे में भूल जाओ - आप जो चाहते हैं वह एप्लिकेशन द्वारा आवंटित वास्तविक स्मृति है। यह एकमात्र तरीका है जिसे आप बता सकते हैं कि क्या आप उस स्मृति को आवंटित कर रहे हैं जिसे समय के साथ मुक्त नहीं किया जा रहा है।

//------------------------------------------------------------------------------ 
// CsiGetApplicationMemory 
// 
// Returns the amount of memory used by the application (does not include 
// reserved memory) 
//------------------------------------------------------------------------------ 
function CsiGetApplicationMemory: Int64; 
var 
    lMemoryState: TMemoryManagerState; 
    lIndex: Integer; 
begin 
    Result := 0; 

    // get the state 
    GetMemoryManagerState(lMemoryState); 

    with lMemoryState do begin 
    // small blocks 
    for lIndex := Low(SmallBlockTypeStates) to High(SmallBlockTypeStates) do 
     Inc(Result, 
      SmallBlockTypeStates[lIndex].AllocatedBlockCount * 
      SmallBlockTypeStates[lIndex].UseableBlockSize); 

    // medium blocks 
    Inc(Result, TotalAllocatedMediumBlockSize); 

    // large blocks 
    Inc(Result, TotalAllocatedLargeBlockSize); 
    end; 
end; 

मैं अपने लॉग फ़ाइल के लिए (कहीं भी 10 सेकंड और 10 मिनट के बीच) को एक अंतराल पर इस प्रवेश करते है, एक साथ पिछली बार से अंतर के साथ: FastMM साथ डेल्फी 2006+ के लिए, यह तुम क्या जरूरत है।

+0

+1 ऐसा कुछ भी मेरा पहला कदम है। यदि आप बाकी सब कुछ रद्द करते हैं, तो पहले पता लगाएं कि क्या आपका ऐप कुछ सूची में स्मृति को हॉगिंग कर रहा है या फिर, या यदि यह "वास्तविक" हेपफ्रैग्मेंटेशन है। –

+0

धन्यवाद मिशा, मैंने अभी तक कोशिश नहीं की है लेकिन यह दिलचस्प लग रहा है, मैं इसे एक शॉट दूंगा - इससे पहले कि मैं केवल छोटे ब्लॉक देख रहा था। – Bourgui

2

क्या आप त्रुटि प्राप्त करते समय हमें एक स्टैक ट्रेस दिखा सकते हैं? त्रुटि के समय यह कितनी मेमोरी का उपभोग करता है?

मैंने कुछ समय पहले मेमोरी लॉगर (फास्टएमएम के लिए) बनाया था जो "सॉफ्ट रिसाव" खोजने के लिए 2 अंक ("स्टार्टॉग" और "एंडलॉग" प्रक्रिया का उपयोग करके) के बीच सभी मेमोरी लॉग करता है: मैं सूची में आवंटन ऑब्जेक्ट्स था लेकिन सूची को कभी भी साफ़ नहीं किया, केवल ऐप बंद करते समय, इसलिए फास्टएमएम ने कोई रिसाव नहीं बताया। मेरी स्मृति लकड़हारा का उपयोग कर मैं उन वस्तुओं मिल सकता तक (यह केवल नए आबंटित स्मृति है कि इससे पहले कि आप "endlog" प्रक्रिया पर अमल जारी नहीं किया गया है लॉग)।
मैं देखता हूं कि मुझे यह कोड मिल सकता है या नहीं।

Btw:

  • FastMM इस त्रुटि जब यह जबकि आवंटन त्रुटि की पहचान देता है: आप एक 3 अन्य तरीकों से "स्मृति से बाहर" मिल सकती है। एक असली "स्मृति से बाहर" लेकिन अधिक एक आंतरिक fastmm त्रुटि (भ्रष्टाचार आदि के कारण)
  • alloc एक बहुत बड़ा ब्लॉक (जैसे 1 जीबी) तो नहीं। मुझे एक बार स्ट्रीम पढ़ने त्रुटि (RemObjects) की वजह से यह मिला, इसलिए यह एक स्ट्रिंग के लिए गलत आकार मान पढ़ता है, इसलिए यह एक (यादृच्छिक) बड़ी स्ट्रिंग को पूर्व-आवंटित करने का प्रयास करता है। इस तरह के एक त्रुटि अजीब लग रहा है, क्योंकि मेरे मामले में मेरे ऐप कोई वास्तविक
  • विखंडन "स्मृति से बाहर" इसलिए भी 150MB के बारे में आवंटित की थी: यदि आप 10 एमबी का एक ब्लॉक alloc करने की कोशिश लेकिन Windows 10 एमबी से एक contineous ब्लॉक नहीं मिल रहा है फिर Windows होगा "स्मृति से बाहर" दें।

तो कृपया त्रुटि के समय उपयोग की गई एक स्टैक ट्रेस और स्मृति की मात्रा दें!

+0

हाय एंड्रे, उत्तर देने के लिए धन्यवाद। मैंने एक स्टैक ट्रेस पोस्ट नहीं किया क्योंकि वे सभी अलग थे। हालांकि, हमें समस्या मिल सकती है, मेरा संपादन देखें। – Bourgui

2

डेल्फी की 32 बिट एड्रेस स्पेस की सीमा के साथ, ऐसी समस्याएं अधिक आम हो रही हैं।

64 बिट ओएस पर चलाने और 2 जीबी उपलब्ध पता स्थान (जैसे आप 32 बिट ओएस पर पहुंचते हैं) से 4 जीबी पते पर चलने वाली पहली और सरल चीज है। यह स्वचालित रूप से नहीं होता है। आपको अपने आवेदन को LARGEADDRESSAWARE के रूप में चिह्नित करने की आवश्यकता है। जोड़ कर ऐसा करें अपने .dpr फ़ाइल में निम्नलिखित:

const 
    IMAGE_FILE_LARGE_ADDRESS_AWARE = $0020; 

{$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE} 

स्मृति त्रुटियों से बाहर के लिए अन्य आम कारण स्मृति का एक shorage है वहाँ है, लेकिन आप सन्निहित स्मृति की एक बड़ी ब्लॉक के लिए पूछ रहे हैं कि नहीं है और पता स्थान का कोई भी एकल ब्लॉक उपलब्ध नहीं है।

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

+0

धन्यवाद डेविड। प्रश्न: फास्टएमएम के साथ उस और/3 जी ध्वज के बीच क्या अंतर है? जैसा कि मैंने अपने संपादन में उल्लेख किया है, मुझे एक समस्या मिली है जो मेरी परेशानियों का स्रोत हो सकती है, और चूंकि मेरी अधिकांश मेमोरी आवंटन अपेक्षाकृत छोटी हैं (वे 10 के एमबी से आगे नहीं जाते हैं) और हमारा आवेदन सिस्टम पर चल रहा है इसका उपयोग किसी और चीज के लिए नहीं किया जा रहा है, मुझे संदेह है (और उम्मीद है!) यह कारण है। उल्लेख नहीं है कि जब भी मैं कर सकता हूं मैं गतिशील सरणी से दूर शर्मिंदा हूं। – Bourgui

+0

@ बॉर्गुई 10 एमबी, बार-बार एक समस्या हो सकती है।/3 जी 32 बिट संस्करण है। आपको अभी भी अपने exe को LARGEADDRESSAWARE के रूप में चिह्नित करने की आवश्यकता है। फिर आपको/3 जीबी के साथ विंडोज बूट करने की जरूरत है। क्या कोई ऐसा करता है? वैसे भी, निश्चित रूप से आपके ग्राहक का सर्वर 64 बिट मशीन है। क्या आप अपने ऐप को LARGEADDRESSAWARE के रूप में चिह्नित कर रहे हैं? यदि नहीं, तो क्यों नहीं? –

+0

इस तरह की बड़ी मेमोरी आवंटन अपेक्षाकृत कम और एप्लिकेशन के बीच बहुत दूर है, जो कि अधिकतम हो सकती है। वे समय-लगातार भी हैं। उन आवंटन भी अच्छी तरह से लॉग इन हैं और हम उन मुद्दों को अपेक्षाकृत आसानी से नोटिस करने में सक्षम होना चाहिए। यही कारण है कि मुझे नहीं लगता कि यह मुद्दा है। लेकिन मैं पूरी तरह से अभी तक कुछ भी बाहर नहीं कर रहा हूँ। सच में, हमारे पास अब तक स्मृति समस्याएं नहीं हैं, इसलिए हमने कभी भी हमारे ऐप को लार्ज एड्रेसवेयर बनाने के लिए प्रोत्साहन नहीं दिया है, लेकिन यह निश्चित रूप से कुछ देखने के लिए है - मैं डेल्फी 64-बिट कंपाइलर के लिए अपनी सांस नहीं रख सकता ! ; ओ) – Bourgui

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