2009-07-09 16 views
5

मैं इस बुरा बग है कि अतीत में गायब हो गया है, लेकिन अब काफी कुछ समय के बाद यह वापस आ था।FastMM4 कहते हैं, "ब्लॉक हैडर दूषित हो गया है"

मैं दो TSam वस्तुओं (TPersistent से प्राप्त) बनाया है और एक TAsmJob वस्तु (TObjectList से प्राप्त) में लोड किया है।

रनटाइम पर, एक रूप एक TStringGrid और फिर AsmJob जो उन दो सैम वस्तुओं बनाता है बनाता है (और उनमें से प्रत्येक में डिस्क से कुछ डेटा लोड)। AsmJob भी ग्रिड को सौंपा गया है। जब फॉर्म नष्ट हो जाता है, तो ग्रिड इसे मुक्त करके AsmJob का ख्याल रखता है, जो टीएसएएम वस्तुओं को मुक्त करता है। यहां समस्या है: पहली वस्तु को समस्याएं मुक्त कर दी गई हैं, लेकिन दूसरा व्यक्ति मर जाता है जब उसकी विरासत विधि (विनाशक को नष्ट करने में) कहा जाता है।

मैं वस्तुओं मुक्त करने के लिए पूरे कार्यक्रम में FreeAndNil का उपयोग करें। टीएसएएम ऑब्जेक्ट्स शून्य नहीं हैं !!!!! तो, वस्तुओं को मुक्त करने का यह पहला प्रयास है। यहां तक ​​कि वस्तुओं के अंदर डेटा भी सुसंगत है।

कार्यक्रम की रीढ़ इस तरह दिखता है:

**Create:** 

Form -> StringGrid 
    -> AsmJob -> Sam1, Sam2 
StringGrid.AsmJob:= AsmJob; 


**Free:** 

Form -> StringGrid -> AsmJob -> Sam1, Sam2 

मैं सच में समझ में नहीं आता है, जहां मैं इस बात की दोबारा मुक्त करने के लिए या वस्तु के ऊपर लिख के बाद इसे जारी कर दिया गया है की कोशिश करो।


संपादित करें:

त्रुटियों मुझे मिल गया में से कुछ:

  • FastMM एक मुक्त ब्लॉक आपरेशन स्कैन के दौरान एक त्रुटि का पता लगाया है। फास्टएमएम ने पाया कि एक ब्लॉक मुक्त होने के बाद संशोधित किया गया है।

  • FastMM एक मुक्त ब्लॉक आपरेशन स्कैन के दौरान एक त्रुटि का पता लगाया है। ब्लॉक हेडर दूषित हो गया है।

विवरण:

The current thread ID is 0x19C, and the stack trace (return addresses) leading to this error is: 
402E77 [System][@FreeMem] 
4068DC [System][@DynArrayClear] 
405E2D [System][@FinalizeArray] 
405D31 [System][@FinalizeRecord] 
40432F [System][TObject.CleanupInstance] 
404272 [System][TObject.FreeInstance] 
404641 [System][@ClassDestroy] 
4D313E [UnitSam.pas][TSam.Destroy][297] 
4042BF [System][TObject.Free] 
4149ED [SysUtils][FreeAndNil] 
4D9C0A [UnitAsmJob.pas][UnitAsmJob][TAsmJob.Destroy][180] 

मैं "रेंज की जांच करें" सहित सभी "डिबग" विकल्प आईडीई में सक्षम है, तो है। इसके अलावा, फास्टएमएम 4 सुपर आक्रामक डीबग मोड पर सेट है। फास्टएमएम के बिना या डीबगर के बाहर प्रोग्राम ठीक चलाता है - लेकिन फिर भी मुझे पता है कि इसका मतलब यह नहीं है कि बग अब और नहीं है। असल में यह एक साल से अधिक के लिए (शायद) काम करता है, जब तक कि मैंने फास्टएमएम स्थापित नहीं किया हो।


संपादित करें:

सभी को धन्यवाद। नहीं, मुझे लगता है कि मैं अच्छी दिशा में थोड़ा आगे बढ़ रहा हूं।

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

मेरे पास एक प्रश्न है: यदि मैं छोटे टुकड़ों में प्रोग्राम को तोड़ने के लिए प्रोग्राम को तोड़ता हूं, तो त्रुटि अभी भी दिखाई देगी? या केवल इस विशेष विन्यास में दिखाना संभव है?


के उत्तर "कैसे AsmJob TStringGrid करने के लिए आवंटित हो जाता है इतना है कि TStringGrid AsmJob नष्ट कर देता है, तो आप हमें दिखा सकते हैं?"

MyGrid = TStringGrid 
    public 
    AsmJob: TAsmJob; 
    end; 

तो TForm.Create (फार्म का है कि ग्रिड रखती है) में कहीं, मैं

MyGrid.AsmJob=AsmJob; 

करते हैं और MyGrid का नाशक में मुझे क्या करना:

begin 
    FreeAndNil(AsmJob); 
    inherited 
end; 

उत्तर

12

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

You should try to use "Range check errors" option (don't forget to make Build, not Compile) and FastMM in full debug mode (with CheckHeapForCorruption, CatchUseOfFreedInterfaces и DetectMMOperationsAfterUninstall options enabled)

आप समस्या के बाद लगभग तुरंत त्रुटि प्राप्त करने के लिए FullDebugModeScanMemoryPoolBeforeEveryOperation वैश्विक चर चालू कर सकते हैं, लेकिन यह विकल्प आपके निष्पादन को धीमा कर देता है।

शायद सबसे अच्छा विकल्प समय-समय पर ScanMemoryPoolForCorruptions को कॉल करता है। इसे एक ही स्थान पर बुलाओ। एक त्रुटि मिली? इसे जल्द कॉल करें। अभी भी एक त्रुटि मिली है? इसे जल्द से जल्द बुलाओ। कोई ग़लती नहीं? आपकी समस्या उन अंतिम कॉल के बीच कहीं भी बैठती है। अब आप सटीक स्थान प्राप्त करने के लिए FullDebugModeScanMemoryPoolBeforeEveryOperation चर का उपयोग कर सकते हैं। बस इसे केवल इस कोड के क्षेत्र पर चालू करें और इसके ठीक बाद इसे बंद करें।

एक बहुत ही समान त्रुटि है: "फास्टएमएम ने पाया कि मुक्त होने के बाद एक ब्लॉक संशोधित किया गया है"। इस मामले में आपका कोड आंतरिक संरचनाओं को संशोधित नहीं करता है, लेकिन अन्य मेमोरी, जिसका उपयोग बिल्कुल नहीं किया जाता है ("फ्री मेमोरी")।

बीटीडब्ल्यू, आपकी त्रुटि डबल-फ्री नहीं है! यदि यह एक डबल-फ्री कॉल है, तो फास्टएमएम आपको स्पष्ट रूप से बताएगा (यह पता लगाना आसान है, क्योंकि आप गैर-उपयोग या अस्तित्व में मौजूद स्मृति ब्लॉक को मुक्त करने की कोशिश नहीं कर रहे हैं): "एक प्रयास को मुक्त/पुनः आवंटित करने का प्रयास किया गया है अनियंत्रित ब्लॉक "।

+0

धन्यवाद अलेक्जेंडर। मुझे "ScanMemoryPoolForCorruptions" के बारे में कोई जानकारी नहीं थी। मुझे लगता है कि फास्टएमएम डीएलएल द्वारा पेश किया गया एक समारोह है। मैं अभी इसके बारे में खोज करने जाउंगा। – Ampere

+0

यह मानक FastMM4.pas से फ़ंक्शन है। यह फास्टएमएम के पूर्ण स्टैंडअलोन संस्करण से है। यह फास्टएमएम के संस्करण में मौजूद नहीं है, जिसे डेल्फी में एकीकृत किया गया है। यहां प्रश्न में कोई डीएलएल नहीं है। यह सामान्य पास फ़ाइल में सिर्फ एक फ़ंक्शन है;) – Alex

+0

दुख की बात है कि लिंक मर चुका है। लेकिन आप इसे यहां एक्सेस कर सकते हैं: http://web.archive.org/web/20091007162116/http://blog.eurekalog.com/?p=198 – EMBarbosa

4

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

+0

हाय मेसन। कोई एएसएम नहीं, कोई कच्चा सूचक ऑपरेशन नहीं है, रेंज जांच हमेशा चल रही है। यह वही है जो मैं आज पूरे दिन को समझने की कोशिश कर रहा हूं: जहां मैं संभवतः उस वस्तु को ओवरराइट कर सकता था। – Ampere

+1

मैंने एक बार पहले इस तरह की स्थिति देखी थी। आखिरकार इसे तीसरी पार्टी लाइब्रेरी में ट्रैक किया गया जिसका उपयोग मैं कच्चे पॉइंटर्स के साथ कुछ परिचालन कर रहा था और उनमें से कुछ को झुका रहा था। क्या यह मामला हो सकता है? –

+0

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

1

कुछ चीजें और मैं पूछ रहा हूं क्योंकि मैं आपका कोड नहीं देख सकता।

को देखते हुए निम्नलिखित कोड:

procedure TForm1.FormCreate(Sender: TObject); 
var 
    wObjLst : TObjectList; 
begin 
    wObjLst := TObjectList.Create; 
    try 
     wObjlst.OwnsObjects := true; 
     wObjlst.Add(TPersistent.Create); 
     wObjlst.Add(TPersistent.Create); 
    finally 
     freeandnil(wObjlst); 
    end; 
end; 

यह बाहर त्रुटि के साथ काम करता है।

आप राज्य है कि

At runtime, a form creates a TStringGrid and then the AsmJob which creates those two SAM objects (and load some data from disk in each of them). The AsmJob is also assigned to the grid. When the form is destroyed, the Grid takes care of the AsmJob by freeing it, which frees the TSam objects. Here is the problem: the first object is freed withot problems but the second one dies when its inherited method (in Destroy destructor) is called.

मेरा पहला सवाल यह है कि AsmJob TStringGrid को असाइन किए जाएंगे करता है, ताकि TStringGrid AsmJob नष्ट कर देता है, तो आप हमें दिखा सकते हैं?

दूसरा, दो ऑब्जेक्ट्स को स्टोर करने के लिए TObjectList के वंशज को क्यों बनाएं और फिर उन्हें स्वयं को बनाने के बजाय उन्हें मुक्त करें और टॉब्जेक्टलिस्ट को ऊपर दिखाए गए अनुसार उन्हें नष्ट कर दें।

कोशिश करने की दूसरी बात fastmm.sourceforge.net से पूर्ण फास्टएमएम 4 पैकेज डाउनलोड करना है, इसे इंस्टॉल करें और फुलडेबग डीएल का उपयोग करें कि यह पता लगाने के लिए कि ऑब्जेक्ट असफल हो रहा है। आप और मैं मानते हैं कि यह एसएएम वस्तुओं में से एक है और यह हो सकता है या नहीं भी हो सकता है।

+0

हाय रयान। मूल रूप से, ऑब्जेक्टलिस्ट को OwnObj = true पर सेट किया गया था, लेकिन अब मैं ऑब्जेक्ट को "मैन्युअल रूप से" मुक्त करता हूं यह देखने के लिए कि त्रुटि कहां दिखाई देती है। इस तरह मैंने यह निर्धारित किया कि त्रुटि टीएसएएम वस्तुओं के विरासत (नष्ट) के कॉल में दिखाई देती है। किसी भी तरह! यदि मैं मैन्युअल रूप से टीएसएएम ऑब्जेक्ट्स बना और उपयोग करता हूं (इसका मतलब है TAsmJob के बिना - जो इन ऑब्जेक्ट्स का एक प्रकार का प्रबंधक है) सबकुछ बस अद्भुत काम करता है। मुझे बिल्कुल कोई त्रुटि नहीं है। -------- पीएस: मेरे पास पहले से ही डीबग मोड में फास्टएमएम है। – Ampere

2

कोड में कहीं भी एक तर्क दौड़ हो सकती है जहां एक वस्तु को मुक्त किया जा रहा है क्योंकि इसे मुक्त किया जा रहा है। यह सुनिश्चित करने के लिए कि यह मामला नहीं है, नल-चेक और अन्य आईपीसी तंत्र (लॉक सूचियां इत्यादि) जोड़ें।

एक और विकल्प कोड को जोड़ने के लिए कोड को उपclass करने के लिए हो सकता है - और यह जांचें कि ऑब्जेक्ट्स को अनुक्रमिक रूप से एक्सेस किया जा रहा है या नहीं।

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