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

यहां एक एमसीवीई है:

#include <thread>
#include <atomic>

class Single
{
public:
    static Single& GetInstance()
    {
        static Single single;
        return single;
    }

    int doSomething()
    {
        while ( !started )
            std::this_thread::sleep_for( std::chrono::milliseconds(100) );

        return 0;
    }

private:
    Single() : 
        started( false ), 
        continueThread( true )
    {
        thread = new std::thread( &Single::threadFunc, this );
    }
    ~Single()
    {
        continueThread = false;
        thread->join();
        delete thread;
    }

    void threadFunc()
    {
        started = true;
        while ( continueThread )
        {
            std::this_thread::sleep_for( std::chrono::milliseconds(1) );
        }
    }

    std::atomic_bool started;
    std::atomic_bool continueThread;
    std::thread* thread;
};

int main( int argc, char* argv[] )
{
    return Single::GetInstance().doSomething();
}

अगर इसे एक main.cpp फ़ाइल में कॉपी किया जाता है और निष्पादित किया जाता है, तो सब कुछ ठीक काम करता है। जब ~Single को डिबगर में निष्पादित किया जाता है, तो मुझे लगता है कि threadFunc थ्रेड चल रहा है और यह पूरी तरह से बंद हो जाता है।

अब, यदि Single परिभाषा और कार्यान्वयन को एक अलग dll में ले जाया जाता है। जब ~Single को डिबगर में निष्पादित किया जाता है, तो मुझे लगता है कि threadFunc थ्रेड अब नहीं चल रहा है (सिस्टम ने इसे पहले ही रोक दिया है) और कोड सफाई से नहीं रुक सकता। विजुअल लीक डिटेक्टर फिर एक मेमोरी लीक की रिपोर्ट करता है।

क्या कोई ध्वज (कोड में या कंपाइलर स्तर पर) है जिसे गारंटी देने के लिए सेट किया जा सकता है कि सिंगलटन हटाए जाने से पहले धागे नष्ट नहीं होते हैं?

मुझे पता है कि मैं main फ़ंक्शन से मैन्युअल रूप से एक deinit फ़ंक्शन को कॉल कर सकता हूं, लेकिन किसी बिंदु पर, main को यह भी पता नहीं हो सकता है कि साझा लाइब्रेरी में सिंगलटन एक थ्रेड चला रहा है जो इसका उपयोग करता है ... पुस्तकालय स्वयं सफाई से बाहर निकलने में सक्षम होना चाहिए।

0
jpo38 30 नवम्बर 2020, 11:04

2 जवाब

सबसे बढ़िया उत्तर

नहीं।

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

समाधान गैर-तुच्छ विनाश अर्थशास्त्र के साथ सिंगलटन, या कोई स्थिर आजीवन चर (वैश्विक, स्थानीय स्थैतिक, वर्ग स्थैतिक) नहीं है। main()/WinMain() में अपनी बात का उदाहरण बनाएं। जिसे इसकी आवश्यकता है, उसके लिए एक संदर्भ पास करें। विध्वंसक को main से बाहर निकलने से पहले इसे साफ करने दें और इस प्रकार सब कुछ अनलोड होने से पहले।

या बस स्मृति रिसाव को अनदेखा करें। प्रक्रिया वैसे भी बाहर निकल रही है।

1
Sebastian Redl 30 नवम्बर 2020, 11:10

यह एसयूओएफ (स्टेटिक यूनिटलाइजेशन ऑर्डर फियास्को) का एक सामान्य मामला है जो स्थैतिक स्थानीय चर का उपयोग करके ऑब्जेक्ट इंस्टेंस लाइफटाइम पर नियंत्रण छोड़ने के कारण होता है। समाधान ऑब्जेक्ट इंस्टेंस लाइफटाइम पर कुछ प्रारंभिक/अप्रारंभिकरण दिनचर्या (शायद आरएआईआई के साथ लपेटा गया) जोड़कर वापस नियंत्रण प्राप्त करना है जो यह सुनिश्चित करेगा कि ऑब्जेक्ट पहले उपयोग से पहले बनाया गया है और अंतिम उपयोग के बाद नष्ट हो गया है लेकिन डीएल अनलोड होने से पहले / main फ़ंक्शन लौट रहा है।

1
user7860670 30 नवम्बर 2020, 11:57