析构函数中的GMock总线错误

时间:2015-09-12 23:11:03

标签: c++ virtual destructor googletest googlemock

我有以下课程:

class D1;
class D2;
class Base
{
Public:
  Base();
  virtual ~Base() { if (instance) delete instance; }
  static Base* GetInstance();

  virtual int Get() = 0;
  virtual int Set(const int val) = 0;
private:
  static Base* instance;
};

Base *Base::instance = nullptr;

Base* Base::GetInstance()
{
  if (some_condition)
    return new D1;
  else
    return new D2;
}

class D1 : public Base
{
public:
...
  virtual int myD1Method()
  {
      ...
  }
  int Get()
  {
     ...
  }
  int Set(const int val)
  {
    ...
  }
private:
// members...
};

class D2 : public Base
{
public:
...
  int Get()
  {
     ...
  }
  int Set(const int val)
  {
    ...
  }
private:
// members...
};

为了测试我的D1类,我使用谷歌模拟框架创建了一个模拟类,如下所示:

class MockD1 : public D1
{
protected:
  using D1::MyD1Method;

  MockD1() : base(Base::GetInstance()) {}

  MOCK_METHOD0(MyD1Method, int())

private:
  Base *base;
};

TEST(MockTest, TestD1)
{
  MockD1 md1;

  EXPECT_CALL(md1, MyD1Method()).WillRepeatedly(Return(10));

  EXPECT_EQ(md1.Set(10), NO_ERROR);
  EXPECT_EQ(md1.Get(), 10);
}

测试似乎工作正常。但是,我在测试结束时遇到了总线错误。当我在gdb中单步执行时,它看起来好像卡在基类析构函数的循环中,最终导致总线错误。我会很感激我对错误的看法。提前谢谢。

1 个答案:

答案 0 :(得分:1)

问题在于这个析构函数:

virtual ~Base() { if (instance) delete instance; }

它与GMock无关。

delete instance正在调用Base::~Base() - 和Base::~Base()调用delete instance - 这是您正在观察的无限循环。

正确的解决方案是不使用单身人士。你可以改用一些工厂。

您还可以尝试在删除实例之前使实例无效 - 这应该有效 - 但仍然 - Base的每个实例都是Base :: instance的所有者(即控制其生命周期)并不是好设计:

 virtual ~Base() 
 {
     Base* instanceToDelete = instance;
     instance = nullptr; 
     if (instanceToDelete) delete instanceToDelete; 
 }