用 GoogleMock 触发内存检查失败而真实对象正常怎么排查:给基类加虚析构函数

用 GoogleMock 触发内存检查失败而真实对象正常怎么排查:给基类加虚析构函数 用 GoogleMock 触发内存检查失败而真实对象正常怎么排查给基类加虚析构函数【免费下载链接】googletestGoogleTest - Google Testing and Mocking Framework项目地址: https://gitcode.com/GitHub_Trending/go/googletest用 GoogleTest/GoogleMock 写 C 测试时你会遇到这样一类堆检查器heap checker报错同一段业务代码依赖换成真实实现时测试正常一旦把依赖替换成 mock 对象堆检查器就报内存错误通常是泄漏。这类现象在 GoogleMock FAQ 里被单列成一问直接给出的排查方向是检查你正在 mock 的那个类通常是纯接口/基类是否声明了虚析构函数。下面按确认现象、定位根因、修复、验证的顺序给出这条排查路径。先确认现象属于这一类动手前先核对失败是否满足这组条件它决定了后文路径是否适用你在测试里 mock 了某个接口/基类并把它分配在堆上new出来的 mock 对象跑测试时堆检查器报内存错误把 mock 换成真实实现后同一个测试就正常通过。满足这三点再按基类缺虚析构函数这条线查。如果换成真实对象也失败或者失败是断言失败而不是堆检查器报错问题就在别处不在本路径范围内。一个容易混淆的相邻原因值得先排除ASSERT_*断言失败会立即从当前函数返回可能跳过后面的清理代码而留下空间泄漏。文档提醒当你在断言失败之外还看到堆检查器报错时要留意这一点见 primer。也就是说堆检查器报错不一定都指向本文的根因需先区分。检查被 mock 的基类是否有虚析构函数FAQ 给出的第一个排查动作是确认被 mock 的类有没有虚析构函数并强调一条通用规则Whenever you derive from a base class, make sure its destructor is virtual. Otherwise Bad Things will happen.即凡是会被继承的基类其析构函数都应当是virtual。文档用下面这段代码文档示例说明问题所在class Base { public: // Not virtual, but should be. ~Base() { ... } ... }; class Derived : public Base { public: ... private: std::string value_; }; ... Base* p new Derived; ... delete p; // ~Base() will be called, but ~Derived() will not // - value_ is leaked.关键在最后几行通过基类指针p删除一个Derived对象时因为~Base()不是虚函数只有~Base()被调用~Derived()不会被调用于是Derived的成员value_这里是一个std::string没有被释放堆检查器据此报泄漏。mock 对象本质上是它所 mock 的接口的一个派生类。当你用接口基类指针持有并删除它时走的正是上面这条派生类析构函数不被调用的路径所以会暴露基类缺虚析构函数的问题。文档还在多处对析构函数不是虚函数给出一致提醒可作为定位时的交叉印证在你准备让别的类继承的任何类上析构函数都必须是虚函数否则通过基类指针删除对象时派生类析构函数不会被调用会得到内存泄漏这类损坏的程序状态见 GoogleMock for dummies。NiceMockT与StrictMockT在T的析构函数不是虚函数时可能无法正常工作见 NiceMock / StrictMock 参考 与 GoogleMock cook book。修复给基类析构函数加 virtual修复动作很小把基类的析构函数声明改成虚函数。以 FAQ 的示例为例把上面的~Base()改成class Base { public: virtual ~Base() { ... } ... };FAQ 给出的成功判定就是这一句By changing~Base()to virtual,~Derived()will be correctly called whendelete pis executed, and the heap checker will be happy.也就是说delete p执行时会正确调用~Derived()之前被跳过的成员释放随之发生堆检查器不再报错。验证先确认测试里确实开着堆检查器。文档提示当你在堆上分配 mock 对象时最好在测试里打开堆检查器如果你已经在用gtest_main库这一点会自动具备见 GoogleMock for dummies。改完基类析构函数后重跑测试堆检查器不再报该 mock 对象相关的内存错误即为修复成功。如果该基类同时被NiceMock/StrictMock包裹修复后这两处可能无法正常工作的提示也随之消除。适用边界本路径只处理mock 对象触发堆检查失败、真实对象正常且根因指向被 mock 基类缺虚析构函数的情况现象不符合这一组条件时不要套用。文档没有给出某个具体平台/工具下如何打开堆检查器的命令只说明使用gtest_main会自带这一点。你实际采用哪种堆检查器需按自己环境确定文档不作指定。【免费下载链接】googletestGoogleTest - Google Testing and Mocking Framework项目地址: https://gitcode.com/GitHub_Trending/go/googletest创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考