2016-10-13 89 views
1

我爲C指針實現了一個自動刪除程序。該代碼適用於測試程序,但是當我在Google Test中使用代碼時,會發生奇怪的事情。我不明白爲什麼。我用未定義的行爲寫了嗎?或者谷歌測試以某種方式干擾?Google測試中的RAII內存損壞

下面的代碼,如果宏ASSERT_THAT被註釋掉,打印:

i1 = 0x8050cf0 
i2 = 0x8050d00 
got: 0x8050cf0 
got: 0x8050d00 
go delete: 0x8050cf0 
go delete: 0x8050d00 

兩個指針的創建,保護得到這些指針,後來將它們刪除。到目前爲止完全符合要求。

如果宏是活動的,其結果是:

i1 = 0x8054cf0 
i2 = 0x8054d00 
got: 0x8054cf0 
got: 0x8054d00 
go delete: 0x8054c01 

出於某種原因,該代碼刪除另一個指針然後一個得了。我完全困惑。你能幫助發現問題嗎?

#include <iostream> 
#include <gmock/gmock.h> 

using namespace testing; 

class Scope_Guard { 
public: 
    Scope_Guard(std::initializer_list<int*> vals) 
    : vals_(vals) 
    { 
    for (auto ptr: vals_) { 
     std::cerr << "got: " << ptr << std::endl; 
    } 
    } 
    ~Scope_Guard() { 
    for (auto ptr: vals_) { 
     std::cerr << "go delete: " << ptr << std::endl; 
     delete ptr; 
    } 
    } 
    Scope_Guard(Scope_Guard const& rhs) = delete; 
    Scope_Guard& operator=(Scope_Guard rhs) = delete; 
private: 
    std::initializer_list<int*> vals_; 
}; 

TEST(Memory, GuardWorksInt) { 
    int* i1 = new int(1); 
    int* i2 = new int(2); 
    std::cerr << "i1 = " << i1 << std::endl; 
    std::cerr << "i2 = " << i2 << std::endl; 
    Scope_Guard g{i1, i2}; 

    ASSERT_THAT(1, Eq(1)); // (*) 
} 

int main(int argc, char** argv) { 
    InitGoogleTest(&argc, argv); 
    return RUN_ALL_TESTS(); 
} 

回答

1

這是未定義的行爲:

您正在複製從構造函數參數一個std::initializer_list成類成員。

複製std::initializer_list不會複製其基本元素。因此,在離開構造函數後,不能保證vals_包含任何有效的東西。

爲成員使用std::vector,並從初始化程序列表構建它。

我不確定你對這個警衛的意圖,但是使用std::unique_ptr可能會更容易。 「

+0

」我不知道你爲什麼寫刪除ptr;在那裏?「在構造函數中獲取輸出也是複製/粘貼錯誤。謝謝你的評論,我編輯了這個問題。 – olpa