析构函数中的模拟总线错误

GMock bus error in destructor

本文关键字:总线 错误 模拟 析构函数      更新时间:2023-10-16

我有以下类:

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类,我使用google mock框架创建了一个模拟类,如下所示:
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中逐步执行时,它看起来好像在基类析构函数中陷入循环,并最终导致总线错误。我会感激任何输入我做错了什么。

这个析构函数的问题是:

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

和GMock没有关系。

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

正确的解决方案是不使用单例。你可以用工厂代替。

你也可以尝试在删除instance之前取消它——这应该可以工作——但仍然——Base的每个实例都是Base::instance的所有者(即控制其生命周期)不是好的设计:

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