2017-03-14 18 views
10

के साथ shared_ptr अजीबता एक कस्टम डिलीटर का उपयोग करते हुए, हमने हाल ही में एक unique_ptr से shared_ptr पर जाने पर एक क्रैश में आया। दुर्घटना तब हुई जब पॉइंटर स्मार्ट पॉइंटर बनाने के लिए इस्तेमाल किया गया था। नीचे कोड है जो समस्या को पुन: उत्पन्न करता है, और काम करने वाले दो मामलों को दिखाता है।null मानों और कस्टम डिलीटर

नीचे दिए गए स्रोत में, एक और दो खुशी से भागते हैं, जबकि "रिलीज़डेस्ट्राय" में तीन क्रैश होते हैं। ऐसा लगता है कि स्मार्ट पॉइंटर में उपयोग की जाने वाली कक्षा में वर्चुअल "रिलीज" होता है और इसलिए प्रोग्राम वी-टेबल देखने की कोशिश कर रहा है। unique_ptr ऐसा लगता है कि यह शून्य पॉइंटर्स के लिए जांच करता है और विनाशक नहीं चलाता है। साझा सूचक इस उपेक्षा को प्रतीत होता है।

क्या किसी को पता है कि यह डिज़ाइन द्वारा है, या यह एसएलएल कार्यान्वयन में एक बग है? हम unique_ptr का दृश्य स्टूडियो 2015.

#include <iostream> 
#include <memory> 

template<class R> 
void ReleaseDestroy(R* r) 
{ 
    r->Release(); 
}; 

class FlatDestroy 
{ 
public : 
    void Release() 
    { 
     delete this; 
    } 
}; 

class VirtualDestroy 
{ 
public: 
    virtual void Release() 
    { 
     delete this; 
    } 
}; 

class SimpleOne 
{ 
public : 
}; 

void main() 
{ 
    std::shared_ptr<SimpleOne> One(nullptr); 
    std::shared_ptr<FlatDestroy> Two(nullptr, ReleaseDestroy<FlatDestroy>); 
    std::shared_ptr<VirtualDestroy> Three(nullptr, ReleaseDestroy<VirtualDestroy>); 

    One.reset(); 
    Two.reset(); 
    Three.reset(); 
} 

उत्तर

12

विनाश व्यवहार का उपयोग कर रहे हैं और shared_ptr अलग हैं:

  • unique_ptr केवल Deleter कॉल करता है, तो इसकी आयोजित सूचक में गैर-शून्य है।

  • shared_ptr हमेशा डिलीटर को कॉल करता है।

तो अपने साझा सूचक Deleter नल पॉइंटर मूल्यों से निपटने के लिए सक्षम होना चाहिए! उदाहरण के लिए, std::free ठीक है, लेकिन std::fclose नहीं है, और न ही आपका डिलीटर है (क्योंकि यह बिना शर्त के r को अस्वीकार करता है)।

संयोग से, यह LWG 2415 में फसलों को बढ़ाता है, जो एक अद्वितीय सूचक से एक साझा सूचक का निर्माण करने का पता लगाता है, जो उस कारण के लिए उस दोष समाधान से पहले टूट गया था। (मैंने इस समस्या को खुद को here पर दबाया है; ध्यान दें कि shared_ptr के लिए शून्य केस को अलग करने के लिए यह कोड सावधानी बरतता है।)

+0

* "चूंकि यह बिना शर्त के संदर्भित करता है" *: इसलिए तीसरा मामला दुर्घटनाग्रस्त हो गया क्योंकि उसने "गैर" - मौजूदा "vtable, जबकि दूसरे मामले में ऐसी कोई तालिका नहीं थी, क्या यह सही है? –

+1

@ एएसएच: दोनों मामले एक शून्य सूचक को खराब कर रहे हैं, जिसके परिणामस्वरूप अपरिभाषित व्यवहार होता है। –

+0

मुझे लगता है, धन्यवाद ... –

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