2012-09-04 56 views
6

使用模板強制編譯器初始化基元/ POD類型值(https://stackoverflow.com/a/11493744/16673http://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

該解決方案似乎使用GCC特定功能(屬性)。根本就沒有理由使用char來存儲?爲什麼不使用原始類型? – Suma

+0

@Suma完全取決於你想完成什麼。零也會很好 - 這只是一個例證。 – justin

4

在Windows API中有一個名爲SecureZeroMemory的函數。你可以看看它的實現。

但是,一般來說,編譯器被迫承認易失性寫入。如果你使變量volatile,它不應該能夠刪除寫入。

+0

你寫的關於volatile的提示可能是一個提示,這個問題的答案應該如何(模板應該在析構函數中使用volatile),但是在我看來,它實際上回答了這個問題(安全變量沒有標記爲volatile ,而且我不希望它被標記爲這樣,如果需要,這應該由模板處理)。 – Suma

+1

@Suma:變量本身不是不穩定的。寫入通過一個易失性表達式就足夠了,比如'* const_cast (this)'。使變量本身具有易變性,確保'this this'本身在任何地方都是'Foo volatile *'而不需要強制轉換,但是在dtor中只需要一個易變的表達式。 – MSalters