2012-09-04 6 views
6

आदिम/पीओडी प्रकार मान (https://stackoverflow.com/a/11493744/16673 या http://www.codeproject.com/Articles/825/Using-templates-for-initialization) प्रारंभ करने के लिए कंपाइलर को लागू करने के लिए टेम्पलेट का उपयोग करने के लिए यह एक आम पैटर्न है।विनाश पर स्वत: मेमोरी ओवरराइट करने के लिए टेम्पलेट

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

उत्तर

3

आप कुछ C++ 11 सुविधाओं का उपयोग कर सकता है यह अधिक पोर्टेबल बनाने के लिए, लेकिन यह एक प्रारंभिक बिंदु के रूप पर्याप्त हो सकता है:

कक्षा

template<typename T> 
class t_secure_destruct { 
    static const size_t Size = sizeof(T); 
    static const size_t Align = alignof(T); 
public: 
    t_secure_destruct() : d_memory() { 
    new(this->d_memory)T; 
    } 

    ~t_secure_destruct() { 
    reinterpret_cast<T*>(this->d_memory)->~T(); 
    this->scribble(); 
    } 

    // @todo implement or delete op-assign and remaining constructors 

public: 
    T& get() { 
    return *reinterpret_cast<T*>(this->d_memory); 
    } 

    const T& get() const { 
    return *reinterpret_cast<const T*>(this->d_memory); 
    } 

private: 
    void scribble() { 
    for (size_t idx(0); idx < Size; ++idx) { 
     this->d_memory[idx] = random(); 
    } 
    } 

private: 
    __attribute__((aligned(Align))) char d_memory[Size]; 
}; 

डेमो

#include <iostream> 

class t_test { 
public: 
    t_test() : a(-1) { 
    std::cout << "construct\n"; 
    } 

    ~t_test() { 
    std::cout << "destruct\n"; 
    } 

public: 
    void print() const { 
    std::cout << "a = " << a << "\n"; 
    } 

public: 
    int a; 
}; 

int main(int argc, const char* argv[]) { 
    t_secure_destruct<t_test>test; 
    test.get().print(); 
    test.get().a = 100; 
    test.get().print(); 
    return 0; 
} 

बेशक, यदि आप पक्ष करते हैं तो आप एक ढेर आवंटन के साथ उस आवंटन को भी वापस कर सकते हैं। यदि आपको एक ऑप्टिमाइज़र को आउटमार्ट करने की आवश्यकता है, तो आपको स्क्रिबलर को इसकी पहुंच से बाहर रखने की आवश्यकता हो सकती है।

+0

ध्वनि उचित। हालांकि रैंडम के साथ पोंछना थोड़ा लाभ लाता है, सादे शून्य को नौकरी करना चाहिए। समाधान मेमोरी चिप्स या इस तरह कुछ ऐसा पढ़ने के खिलाफ सुरक्षित करने का प्रयास नहीं करता है, बस स्मृति तक पहुंचने वाली दूसरी प्रक्रिया के खिलाफ। या ऐसे मामले में भी यादृच्छिक डेटा का उपयोग करने का कोई कारण है? – Suma

+0

समाधान जीसीसी विशिष्ट विशेषताओं (विशेषताओं) का उपयोग कर रहा है। क्या भंडारण के लिए चार का उपयोग करने का कोई कारण है? मूल प्रकार का उपयोग क्यों नहीं कर रहे हैं? – Suma

+0

@ सुमा यह पूरी तरह से निर्भर करता है कि आप क्या हासिल करना चाहते हैं। शून्य भी अच्छा होगा - यह सिर्फ एक उदाहरण है। – justin

4

विंडोज एपीआई में एक फंक्शन है जिसे SecureZeroMemory कहा जाता है। आप इसे कार्यान्वित कर सकते हैं।

हालांकि, आम तौर पर बोलते हुए, कंपाइलर को अस्थिर लेखन का सम्मान करने के लिए मजबूर किया जाता है। यदि आप परिवर्तनीय अस्थिर बनाते हैं, तो यह लिखने को हटाने में सक्षम नहीं होना चाहिए।

+0

अस्थिरता के बारे में आप जो लिखते हैं वह शायद एक संकेत है कि इस प्रश्न का उत्तर कैसा दिखता है (टेम्पलेट शायद विनाशक में अस्थिरता का उपयोग करना चाहिए), लेकिन ऐसा लगता है कि यह वास्तव में प्रश्न का उत्तर देता है (सुरक्षित चर को अस्थिर चिह्नित नहीं किया जाता है , और मुझे उम्मीद नहीं है कि इसे इस तरह चिह्नित किया जाए, यदि आवश्यक हो तो इसे टेम्पलेट द्वारा संभाला जाना चाहिए)। – Suma

+1

@ सुमा: इससे कोई फर्क नहीं पड़ता कि परिवर्तनीय स्वयं अस्थिर नहीं है। यह पर्याप्त है कि लेखन एक अस्थिर अभिव्यक्ति के माध्यम से है, जैसे '* const_cast (यह) '। परिवर्तनीय स्वयं को अस्थिर बनाना सुनिश्चित करता है कि 'यह' हर जगह जानवरों के बिना 'फू अस्थिर * * है, लेकिन आपको केवल डीटीआर में अस्थिर अभिव्यक्ति की आवश्यकता है। – MSalters