Google Test Sample10:通过listener API进行内存泄露检查 v0.6
一、环境信息
- Visual Studio 2019
- Windows 10
二、Google Test Sample10
1. 示例概述
1.1 sample10演示了如何通过Google Test的listener API进行内存泄露检查(在示例9中展示了通过 listener API实现控制台的定制化输出)
1.2 示例10中先定义了一个新类,随后通过listener监控类对象的创建和释放,判定是否存在内存泄露的情况
2. 目前的问题(原因已查明,待解决)
2.1 sample10可以编译通过并正常执行,但是代码中的预定目标没有实现:内存泄露报警
–原因分析:和示例9一样,需要带参数运行gtest,但是在VS 2019默认条件下,不会带参数执行,也就是说 sample09 sample10均需要带参数独立运行
2.2 示例10也是gtest API的具体使用。这个使用场景可能并不多,目前先不深究,等实际用到了再说
3. 对应的单元测试用例
3.1 sample10详细代码及个人注释如下
#include "pch.h"
// This sample shows how to use Google Test listener API to implement a primitive leak checker.
// sample10:通过gtest的listener接口进行内存泄露检测 //在sample09中,listener接口演示了如何自定义控制台打印输出信息
#include <stdio.h>
#include <stdlib.h>
//#include "gtest/gtest.h"
using ::testing::EmptyTestEventListener;
using ::testing::InitGoogleTest;
using ::testing::Test;
using ::testing::TestEventListeners;
using ::testing::TestInfo;
using ::testing::TestPartResult;
using ::testing::UnitTest;
namespace
{
// We will track memory used by this class. //跟踪类Water的内存使用
class Water
{
private:
static int allocated_;
public:
// Normal Water declarations go here.
// operator new and operator delete help us control water allocation.
void *operator new(size_t allocation_size) //通过operator重新定义了new:除分配内存空间外,计数器增加
{ //*operator?
allocated_++;
return malloc(allocation_size);
}
void operator delete(void* block, size_t /* allocation_size */)
{ 通过operator重新定义了delete:除释放内存空间外,计数器减少
allocated_--;
free(block);
}
static int allocated() //allocated()函数可以返回当前计数器的值
{
return allocated_;
}
};
int Water::allocated_ = 0;
// This event listener monitors how many Water objects are created and destroyed by each test,
// and reports a failure if a test leaks some Water objects.
// listener用于监控测试中共有多少类对象被创建和删除,如果存在泄漏,则上报失败。通过比对测试前后的类对象数量进行监控
// It does this by comparing the number of live Water objects at the beginning of a test and at the end of a test.
class LeakChecker : public EmptyTestEventListener
{
private:
// Called before a test starts. //测试开始时,读取类Water中计数器的值
void OnTestStart(const TestInfo& /* test_info */) override
{
initially_allocated_ = Water::allocated();
}
// Called after a test ends. //测试结束后,读取类Water中计数器的值并与初始值相减
// 若内存不泄露,当前读取的值 一定小于等于 初始值
void OnTestEnd(const TestInfo& /* test_info */) override
{
int difference = Water::allocated() - initially_allocated_;
// You can generate a failure in any event handler except OnTestPartResult.
// Just use an appropriate Google Test assertion to do it. // << 中的信息在用例执行失败后触发
EXPECT_LE(difference, 0) << "Leaked " << difference << " unit(s) of Water!";
}
int initially_allocated_;
};
TEST(ListenersTest, DoesNotLeak)
{
Water* water = new Water;
delete water;
}
// This should fail when the --check_for_leaks command line flag is specified.
//
TEST(ListenersTest, LeaksWater) //只有new分配内存 没有delete释放内存 一定会触发内存泄露
{
Water* water = new Water;
EXPECT_TRUE(water != nullptr);
}
} // namespace
int main2(int argc, char** argv) //int main(int argc, char** argv)?
{
InitGoogleTest(&argc, argv); //InitGoogleTest?
bool check_for_leaks = false;
if (argc > 1 && strcmp(argv[1], "--check_for_leaks") == 0) //若用例带参数 --check_for_leaks 执行,check_for_leaks赋值为true
check_for_leaks = true;
else
printf("%s\n", "Run this program with --check_for_leaks to enable "
"custom leak checking in the tests.");
// If we are given the --check_for_leaks command line flag, installs the leak checker.
//
if (check_for_leaks)
{
TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
// Adds the leak checker to the end of the test event listener list,
// after the default text output printer and the default XML report
// generator.
//
// The order is important - it ensures that failures generated in the
// leak checker's OnTestEnd() method are processed by the text and XML
// printers *before* their OnTestEnd() methods are called, such that
// they are attributed to the right test. Remember that a listener
// receives an OnXyzStart event *after* listeners preceding it in the
// list received that event, and receives an OnXyzEnd event *before*
// listeners preceding it.
//
// We don't need to worry about deleting the new listener later, as
// Google Test will do it.
listeners.Append(new LeakChecker);
}
return RUN_ALL_TESTS();
}