Google Mock Linux上的免费系统功能总是以内存泄漏结束

Google Mock Linux上的免费系统功能总是以内存泄漏结束,linux,memory-leaks,mocking,debian-based,Linux,Memory Leaks,Mocking,Debian Based,我试图模拟Linux标准库中的一个简单函数strerror()从错误号返回错误消息。这是我的库,具有模拟功能: ~$ cat mylib.c #include <string.h> #include <stdio.h> int myStrerror() { int error_number = 0; char* buffer = strerror(error_number); fprintf(stdout, "Returned str

我试图模拟Linux标准库中的一个简单函数
strerror()
从错误号返回错误消息。这是我的库,具有模拟功能:

~$ cat mylib.c
#include <string.h>
#include <stdio.h>

int myStrerror()
{
    int error_number = 0;

    char* buffer = strerror(error_number);
    fprintf(stdout, "Returned string =  '%s'\n", buffer);
    return 0;
}

#if defined (EXECUTABLE)
int main(int argc, char **argv)
{
    return myStrerror();
}
#endif

~$ g++ -pedantic-errors -Wall -c mylib.c
这是它正常返回的结果:

~$ ./mylib.a
Returned string = 'Success'
运行测试可以得到以下结果:

~$ ./test_mylib.a
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from MockTestSuite
[ RUN      ] MockTestSuite.strerror
Returned string = 'mocked strerror function'
[       OK ] MockTestSuite.strerror (0 ms)
[----------] 1 test from MockTestSuite (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.
test_mylib.cpp:32:错误:应删除此模拟对象(在test MockTestSuite.strerror中使用),但决不删除。其地址为@0x56114aa239e0。
错误:在程序出口处发现1个泄漏的模拟对象。当模拟对象被破坏时,验证对该对象的期望。泄漏模拟意味着它的期望没有得到验证,这通常是一个测试错误。如果您确实打算泄漏模拟,可以使用testing::mock::AllowLeak(mock_对象)抑制此错误,也可以使用假或存根代替模拟


如何避免内存泄漏?

问题是我们使用了系统库中的一个免费全局函数
strerror()
。它并不像Googlemock那样被界面模仿。所以我们不需要接口。我们必须用一个自由函数覆盖模拟函数,该函数必须是全局函数,才能与系统函数在同一范围内,因为它将替换它。这就是我们要做的:

strerrorMock strerrorMockObj;

char* strerror(int error_number) {
    return strerrorMockObj.strerror(error_number);
}
这里mock的实例
strerrorMockObj
也在全局范围内,可以在函数中调用。但很明显,Googletest无法删除错误消息中提到的全局模拟对象。我发现的一个解决方案是,像往常一样在测试宏中实例化mock对象,并存储指向它的全局指针,以便函数可以对其进行寻址:

strerrorMock* ptrStrerrorMockObj;
char* strerror(int error_number) {
    return ptrStrerrorMockObj->strerror(error_number);
}

TEST(MockTestSuite, strerror)
{
    strerrorMock strerrorMockObj;
    ptrStrerrorMockObj = &strerrorMockObj;
...
}
然后,完整的测试程序(无内存泄漏)如下所示:

~$ cat test_strerror.cpp
#include "gtest/gtest.h"
#include "gmock/gmock.h"

int myStrerror();

class strerrorMock {
public:
    MOCK_METHOD(char*, strerror, (int));
};

strerrorMock* ptrStrerrorMockObj;
char* strerror(int error_number) {
    return ptrStrerrorMockObj->strerror(error_number);
}

TEST(MockTestSuite, strerror)
{
    using ::testing::Return;

    strerrorMock strerrorMockObj;
    ptrStrerrorMockObj = &strerrorMockObj;

    char mockedstr[] = "mocked strerror function";
    EXPECT_CALL(strerrorMockObj, strerror(0))
        .WillOnce(Return(mockedstr));
    EXPECT_EQ(myStrerror(), 0);
}

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
~$ cat test_strerror.cpp
#include "gtest/gtest.h"
#include "gmock/gmock.h"

int myStrerror();

class strerrorMock {
public:
    MOCK_METHOD(char*, strerror, (int));
};

strerrorMock* ptrStrerrorMockObj;
char* strerror(int error_number) {
    return ptrStrerrorMockObj->strerror(error_number);
}

TEST(MockTestSuite, strerror)
{
    using ::testing::Return;

    strerrorMock strerrorMockObj;
    ptrStrerrorMockObj = &strerrorMockObj;

    char mockedstr[] = "mocked strerror function";
    EXPECT_CALL(strerrorMockObj, strerror(0))
        .WillOnce(Return(mockedstr));
    EXPECT_EQ(myStrerror(), 0);
}

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}