2016-10-13 50 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