memory management - बीडीएस 2006 सी छिपी हुई मेमोरी मैनेजर संघर्ष(कक्षा नया/हटाएं[] बनाम एएनआईस्ट्रिंग)



memory-management struct (1)

मैं अब बीडीएस 2006 टर्बो सी ++ का उपयोग कर रहा हूं और अब मेरी कुछ बड़ी परियोजनाएं ( सीएडी / सीएएम, 3 जी जीएफएक्स इंजन और एस्ट्रोनॉमिक कंप्यूटेशन) कभी-कभी एक अपवाद फेंक देते हैं (उदाहरण के लिए एक बार में 3-12 महीनों में 24/7 भारी शुल्क उपयोग )। व्यापक डीबगिंग के बाद मुझे यह मिला:

//code1:
struct _s { int i; }    // any struct
_s *s=new _s[1024];     // dynamic allocation
delete[] s;             // free up memory

यह कोड आमतौर पर टेम्प्लेट में होता है जहां _s कक्षा भी हो सकती है इसलिए इस कोड को ठीक से काम करना चाहिए delete[] , लेकिन delete[] स्ट्रेंक्ट्स के लिए ठीक से काम नहीं करता (वर्ग ठीक दिखता है)। कोई अपवाद नहीं फेंक दिया जाता है, स्मृति मुक्त हो जाती है, लेकिन यह किसी भी तरह से स्मृति प्रबंधक आवंटन तालिकाओं को नुकसान पहुंचाता है और इसके बाद कोई नया आवंटन गलत हो सकता है (नया पहले से आबंटित आवंटित या आवंटित स्थान के साथ अतिव्यापी आबंटन बना सकता है, इसलिए कभी-कभी अपवाद)

मैंने पाया है कि अगर मैं खाली नाशक को _s से अचानक जोड़ता हूं तो ठीक से सबकुछ ठीक लगता है

struct _s { int i; ~_s(){}; }

खैर अब अजीब हिस्सा आता है। मेरे प्रोजेक्ट्स में इसे अपडेट करने के बाद मैंने पाया है कि AnsiString क्लास में भी बुरा पुन: उदाहरण के लिए:

//code2:
int i;
_s *dat=new _s[1024];
AnsiString txt="";
// setting of dat
for (i=0;i<1024;i++) txt+="bla bla bla\r\n";
// usage of dat
delete[] dat;

इस कोड में कुछ उपयोगी डेटा शामिल हैं, फिर बाद में कुछ txt स्ट्रिंग बनाई गई है जिससे लाइनें जोड़ दी जाती हैं, इसलिए टेक्सटाइल को कुछ बार फिर से आवंटित किया जाना चाहिए और कभी-कभी डेटा डेटा को टीएसटीटी द्वारा ओवरराइट किया जा सकता है (भले ही वे ओवरलैप न हो जाएं, मैं अस्थायी AnsiString txt reallocate करने के लिए dat साथ ओवरलैप है)

तो मेरे सवाल हैं:

  1. क्या मैं कोड 1, कोड 2 में कुछ गलत कर रहा हूं?
  2. क्या AnsiString (पुनः) आवंटन त्रुटियों से बचने का कोई तरीका है? (लेकिन अभी भी इसका उपयोग करते हुए)

    • विस्तृत डीबगिंग के बाद (प्रश्न 2 पोस्ट करने के बाद) मैंने पाया है कि AnsiString समस्याएं पैदा नहीं करता है। उनका उपयोग करते समय वे केवल तभी होते हैं वास्तविक समस्या शायद ओपनजीएल ग्राहकों के बीच स्विच करने में है। मेरे पास वेक्टर ग्राफिक्स के लिए पूर्वावलोकन के साथ ओपन / सहेजें संवाद है अगर मैं ओनिगेल का उपयोग इन वीसीएल उप-विंडो के लिए AnsiString स्मृति प्रबंधन त्रुटियों से पूरी तरह से गायब हो जाता है मैं किन बात नहीं है ( एमएफसी / वीसीएल खिड़कियों के बीच असंगति या अधिक होने की वजह से मैं संदर्भों को बदलने में कुछ गलती की है, आगे की जांच करेगा)। ओपनजीएल विंडोज़ की चिंता:
    • मुख्य वीसीएल फॉर्म + ओपन जीएल Canvas क्लाइंट एरिया के अंदर
    • मुख्य एमएफसी का बच्चा खुला / सहेजें संवाद + डॉकेड पूर्वावलोकन वीसीएल फॉर्म + ओपनजीएल Canvas क्लाइंट एरिया के अंदर

पुनश्च

  1. ये त्रुटियां new/delete/delete[] संख्याओं पर निर्भर करती हैं new/delete/delete[] आवंटित आकारों पर नहीं होती हैं
  2. दोनों code1 और code2 त्रुटियाँ दोहराव (उदाहरण के लिए जटिल INI फ़ाइल को लोड करने के लिए एक पार्सर है और त्रुटि समान पंक्ति पर होती है यदि INI नहीं बदला गया है)
  3. मैं इन त्रुटियों को केवल बड़ी परियोजनाओं (सादा स्रोत कोड> 1 एमबी) पर AnsiString और आंतरिक गतिशील आवंटन के साथ टेम्पलेट्स के संयुक्त उपयोग के साथ AnsiString हूं, लेकिन संभव है कि वे सरल परियोजनाओं में भी हैं लेकिन ऐसा इसलिए होता है कि मुझे यह याद आती है
  4. संक्रमित परियोजनाएं चश्मा:
    • Win32 noinstall स्टैंडअलोन ( Win7sp1 x64 का उपयोग करते हुए, लेकिन XPsp3 x32 पर एक ही व्यवहार करता है)
    • अगर GDI या ओपनजीएल / जीएलएसएल का उपयोग नहीं करता तो मीटर नहीं
    • मीटर उपयोग नहीं करता है अगर डिवाइस ड्रायवर डीएलएल का उपयोग करें या नहीं
    • कोई ओसीएक्स नहीं, या गैर-मानक VCL घटक
    • कोई डायरेक्टएक्स नहीं
    • 1 बाइट संरेखित संकलन / लिंक
    • आरटीएल , पैकेज या चौखटे (स्टैंडअलोन) का उपयोग न करें

खराब अंग्रेजी / व्याकरण के लिए क्षमा करें ... किसी भी मदद / निष्कर्ष / सुझाव की सराहना की।


व्यापक डिबगिंग के बाद मैंने समस्या को अलग से अलग किया। बीडीएस -2006 के मेमोरी प्रबंधन टर्बो सी ++ आप पहले से ही हटाए गए पॉइंटर के लिए किसी भी डिलीट को कॉल करने का प्रयास करने के बाद भ्रष्ट हो गए। उदाहरण के लिए:

BYTE *dat=new BYTE[10],*tmp=dat;
delete[] dat;
delete[] tmp;

इसके बाद स्मृति प्रबंधन विश्वसनीय नहीं है ('नया' पहले से आवंटित स्थान आवंटित कर सकता है)

बेशक एक ही संकेतक को दो बार नष्ट करना प्रोग्रामर पक्ष पर बग है, लेकिन मुझे यह समस्या उत्पन्न करने वाली सभी समस्याओं का वास्तविक कारण मिला है (स्रोत कोड में कोई स्पष्ट बग के बिना) यह कोड देखें:

//---------------------------------------------------------------------------
class test
    {
public:
    int siz;
    BYTE *dat;
    test()
        {
        siz=10;
        dat=new BYTE[siz];
        }
    ~test()
        {
        delete[] dat;   // <- add breakpoint here
        siz=0;
        dat=NULL;
        }
    test& operator = (const test& x)
        {
        int i;
        for (i=0;i<siz;i++) if (i<x.siz) dat[i]=x.dat[i];
        for (   ;i<siz;i++) dat[i]=0;
        return *this;
        }
    };
//---------------------------------------------------------------------------
test get()
    {
    test a;
    return a;   // here call a.~test();
    }           // here second call a.~test(); 
//---------------------------------------------------------------------------
void main()
    {
    get();
    }
//---------------------------------------------------------------------------

फ़ंक्शन में get() को कक्षा के लिए डिस्ट्रक्टर कहा जाता है, दो बार। एक बार असली कॉपी और इसकी प्रतिलिपि के लिए क्योंकि मैं कन्स्ट्रक्टर बनाने के लिए भूल गया हूं

test::test(test &x);

[संपादन 1] कोड का और उन्नयन

ठीक है मैंने क्लास और स्टार्ट के लिए इनिशियलाइज कोड को भी परिष्कृत किया है, यहां तक ​​कि अधिक बग मामलों को ठीक करने के लिए टेम्पलेट्स भी हैं। किसी भी संरचना / वर्ग / टेम्पलेट में इस कोड को जोड़ें और यदि कार्यक्षमता जोड़ने की तुलना में आवश्यक है

T()     {}
T(T& a) { *this=a; }
~T()    {}
T* operator = (const T *a) { *this=*a; return this; }
//T* operator = (const T &a) { ...copy... return this; }
  • T स्ट्रेट / क्लास का नाम है
  • आखिरी ऑपरेटर केवल तभी आवश्यक है जब T कोई आवंटन का उपयोग नहीं किया जाता है, तो इसके अंदर गतिशील आवंटन का उपयोग किया जाता है, जैसा कि आप इसे छोड़ सकते हैं

यह अन्य संकलक मुद्दों को भी इस तरह से हल करता है:

  • Bcc32 में एक सरल सरणी के लिए कई प्रारंभिक त्रुटि

अगर किसी को भी इसी तरह की समस्याएं हैं तो यह मदद करता है

यदि आपको अपनी मेमोरी आवंटन डिबग करने की आवश्यकता है, तो सी + + कोड mmap में ट्रेसबैक को एक सूचक देखें ...





c++builder-2006