2010-06-01 18 views
7

मुझे समझ में नहीं आ रहा है कि निम्न कोड मेमोरी लीक क्यों उत्पन्न करता है (मैं स्थिर वर्ग उदाहरण के साथ boost::shared_ptr का उपयोग कर रहा हूं)। क्या कोई मेरी मदद कर सकता है?सी ++ स्थिर वर्ग और साझा_पीटीआर मेमोरी लीक

#include <crtdbg.h> 
#include <boost/shared_ptr.hpp> 
using boost::shared_ptr; 

#define _CRTDBG_MAP_ALLOC 
#define NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) 

static struct myclass { 
    static shared_ptr<int> ptr; 

    myclass() { 
     ptr = shared_ptr<int>(NEW int); 
    } 
} myclass_instance; 

shared_ptr<int> myclass::ptr; 

int main() { 
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | 
        _CRTDBG_CHECK_ALWAYS_DF | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)); 
    return 0; 
} 
+0

पैरामीटर या सूची के अंदर '_CrtSetDbgFlag()' पर दूसरी कॉल क्यों है? – sharptooth

+0

यह दो बयानों को एक –

+0

में संयोजित करने का एक तरीका है, मुझे यह नहीं मिलता है। आप "या" चार झंडे क्यों नहीं करते हैं बल्कि इसके बजाय फ़ंक्शन insidethe "या" सूची को कॉल करते हैं? – sharptooth

उत्तर

8
एक अनुमान पर

सीआरटी एक झूठी सकारात्मक रिपोर्ट कर रहा है - निम्नलिखित कोड दिखाता है कि साझा सूचक कम से कम छ ++

#include <iostream> 
#include "boost/shared_ptr.hpp" 
using namespace std; 
using namespace boost; 

struct R { 
    R() { 
     cerr << "ctor" << endl; 
    } 

    ~R() { 
     cerr << "dtor" << endl; 
    } 
}; 

struct A { 
    static shared_ptr<R> ptr; 

    A() { 
    ptr = shared_ptr<R>(new R); 
    } 

}; 

shared_ptr<R> A::ptr; 
static A a; 

int main() { 
} 

यह प्रिंट के साथ सही ढंग से काम कर रहा है,:

ctor 
dtor 
+0

परीक्षण कोड के लिए +1 – neuro

8

सबसे अधिक संभावना रिसाव से पहले वैश्विक वस्तुओं नष्ट हो और shared_ptr वस्तु जारी करने के लिए एक मौका है का पता चला है, इसलिए संभव है एक झूठी रिसाव है।

11

यह वह जगह है एक स्मृति रिसाव। आप myclass_instance नामक myclass का स्थिर उदाहरण प्रारंभ कर रहे हैं। आप "shared_ptr myclass :: ptr" भी शुरू कर रहे हैं।

स्ट्राउस्ट्रप [3] के अनुसार, आंकड़े परिभाषित किए गए क्रम में प्रारंभ किए गए हैं। इसलिए आपके पास myclass_instance की स्थिर परिभाषा है, जो निर्माण पर आंतरिक पीआरटी शुरू करती है। हालांकि, आपके पास स्थिर myclass :: ptr की परिभाषा है, जो shared_ptr के लिए डिफ़ॉल्ट कन्स्ट्रक्टर को आमंत्रित करती है।

यह क्लासिक स्टेटिक्स ऑर्डरिंग समस्या का एक उदाहरण है। संकलक सोचता है कि myclass :: ptr वास्तव में प्रारंभ नहीं किया गया था, इसलिए मूल shared_ptr का कोई विनाश नहीं है। इसके बजाए, यह सिर्फ लीक है।

आपको किसी प्रकार का बेयर पॉइंटर चाहिए। यदि आप सी ++ 11 का उपयोग कर रहे हैं, तो आप निफ्टी काउंटर तकनीक को एक टर्नरी असाइनमेंट कथन के साथ कर सकते हैं जो आपके लिए एक कदम है यदि आप यह निर्धारित करते हैं कि ऑब्जेक्ट पहले ही शुरू हो चुका है। यह बहुत मोटा है, लेकिन यह काम करता है।

यहाँ कैसे मैं इसे में क्या चाहते हैं सी ++ 11 है:

#include <crtdbg.h> 
#include <memory> 
using std; 

#define _CRTDBG_MAP_ALLOC 
#define NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) 

// Note that the count could also be a field in an initializer static used in the Nifty Counter 
// Technique covered in many texts. 
static int count = 0; // This gets implicitly initialized to 0 by the executable load into memory. 
static struct myclass { 
    static shared_ptr<int> ptr; 

    myclass() { 
     if (count++ == 0) { 
     ptr = make_shared<int>(0); //initialization 
     } 
    }   
} myclass_instance; 

shared_ptr<int> myclass::ptr = count == 0 ? make_shared<int>(0) : move(myclass::ptr); 

int main() { 
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | 
        _CRTDBG_CHECK_ALWAYS_DF | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)); 
    return 0; 
} 

अधिक जानकारी के लिए निम्न देखें:

  1. Lakos, जम्मू, 1996, बड़े पैमाने पर सी ++ सॉफ्टवेयर डिजाइन। धारा 7.8.1.3, एडिसन वेस्ले, पढ़ना, मैसाचुसेट्स।
  2. मेयर्स, एस, 2005, प्रभावी सी ++, तीसरा संस्करण। आइटम 4: सुनिश्चित करें कि वस्तुओं का उपयोग करने से पहले प्रारंभ किया गया है। एडिसन वेस्ले, रीडिंग, मैसाचुसेट्स।
  3. स्ट्राउस्ट्रप, बी, 2000, सी ++ प्रोग्रामिंग भाषा विशेष संस्करण। धारा 10.4.9, एडिसन वेस्ले, पढ़ना, मैसाचुसेट्स।
+0

मुझे लगता है कि यह एकमात्र सही उत्तर है, ए और ए :: पीआरआर के क्रम के बाद से एनन द्वारा पहले जवाब सही ट्रांसक्रिप्शन नहीं है। –

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