【问题标题】:Double free in Google MockGoogle Mock 中的双倍免费
【发布时间】:2017-04-07 08:44:38
【问题描述】:

我是 Google 测试和模拟框架的新手。

我只是尝试运行“Turtle”示例,它是成功的。

但是,显示错误消息:双重释放或损坏 (!prev)。

MockTurtle.h

#include <gmock/gmock.h>

class MockTurtle : class Turtle {
    MOCK_METHOD0(PenUp, void());
    MOCK_METHOD0(PenDown, void());
    MOCK_METHOD1(Forward, void(int distance));
    MOCK_METHOD1(Turn, void(int degrees));
    MOCK_METHOD2(GoTo, void(int x, int y));
    MOCK_CONST_METHOD0(GetX, int());
    MOCK_CONST_METHOD0(GetY, int());
};    

Turtle.h

class Turtle {
    virtual ~Turtle() {}
    virtual void PenUp() = 0;
    virtual void PenDown() = 0;
    virtual void Forward(int distance) = 0;
    virtual void Turn(int degrees) = 0;
    virtual void GoTo(int x, int y) = 0;
    virtual int GetX() const = 0;
    virtual int GetY() const = 0;
};    

Painter.h

class Painter    
{
       Turtle* turtle;
public:
       Painter( Turtle* turtle )
               :       turtle(turtle){}

       bool DrawCircle(int, int, int){
               turtle->PenDown();
               return true;
       }
};    

Main_test.cpp

#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "Painter.h"
#include "MockTurtle.h"

using ::testing::AtLeast;

TEST(PainterTest, CanDrawSomething) {
 MockTurtle turtle;
 EXPECT_CALL(turtle, PenDown())
     .Times(AtLeast(1));

 Painter painter(&turtle);

 EXPECT_TRUE(painter.DrawCircle(0, 0, 10));
}

int main(int argc, char** argv) {
 // The following line must be executed to initialize Google Mock
 // (and Google Test) before running the tests.
 ::testing::InitGoogleMock(&argc, argv);
 return RUN_ALL_TESTS();
}    

结果

[==========] Running 1 test from 1 test case.    
[----------] Global test environment set-up.
[----------] 1 test from PainterTest
[ RUN      ] PainterTest.CanDrawSomething
[       OK ] PainterTest.CanDrawSomething (0 ms)
[----------] 1 test from PainterTest (0 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (1 ms total)
[  PASSED  ] 1 test.
*** Error in `/home/user/workspace/google_mock_2/Debug/google_mock_2': double free or corruption (!prev): 0x098a8080 ***

我尝试谷歌,看到几个相同的问题。人们说不应该使用 mock 作为全局变量。

但是我的例子没有使用全局变量。

请帮我解释为什么会发生双重免费。 提前致谢!

【问题讨论】:

  • 我已经添加了更多源代码。这就是我的例子。

标签: c++ unit-testing googletest googlemock


【解决方案1】:

上次,我在 SHARED 库中构建了 google test 和 google mock。 并且发生了错误(双重释放)。

我尝试构建为 STATIC 库。此错误不再出现。 我不知道为什么,但我会调查以了解更多细节。

【讨论】:

    【解决方案2】:

    我有同样的问题。就我而言,问题在于将谷歌测试和谷歌模拟链接起来。我只是通过链接 gmock 解决了这个问题,没有 gtest。

    我认为这是因为,据我了解,gmock 已经静态链接 gtest:当您将 gmock 编译为动态库时,gtest 也会在构建 gmock 的同一文件夹中生成(作为静态库)。我想 gmock 依赖并使用这个库。

    我想,以某种方式,链接 gtest 两次(静态和动态)会产生一个 free() 来执行两次。

    【讨论】:

      【解决方案3】:

      供您参考,这是用于 CMake 共享库构建的 gtest/gmock 中的一个错误。已通过this pull request 解决。有关更多详细信息,请阅读issue 930 中的讨论。

      【讨论】:

        【解决方案4】:

        您的错误出现在您没有向我们展示的地方。我设法添加了足够的标题和定义来编译您的示例:

        #include <gtest/gtest.h>
        #include <gmock/gmock.h>
        
        class Turtle {
        public:
            virtual ~Turtle() = default;
            virtual void PenDown() = 0;
        };
        
        class MockTurtle : public Turtle {
        public:
            MOCK_METHOD0(PenDown, void());
        };
        
        
        class Painter
        {
            Turtle *turtle;
        
        public:
            Painter(Turtle *turtle)
                : turtle(turtle)
            {}
        
            bool DrawCircle(int, int, int)
            {
                turtle->PenDown();
                return true;
            }
        };
        
        TEST(PainterTest, CanDrawSomething)
        {
            MockTurtle turtle;
            EXPECT_CALL(turtle, PenDown()).Times(testing::AtLeast(1));
        
            Painter painter(&turtle);
            EXPECT_TRUE(painter.DrawCircle(0, 0, 10));
        }
        

        使用这个makefile:

        VPATH += $(GTEST_DIR)/src
        VPATH += $(GMOCK_DIR)/src
        gtest%.o: CPPFLAGS += -I$(GTEST_DIR)
        gmock%.o: CPPFLAGS += -I$(GMOCK_DIR)
        
        40762798: CXXFLAGS += -isystem $(GTEST_DIR)/include -isystem $(GMOCK_DIR)
        40762798: CXXFLAGS += -pthread -Wno-effc++
        40762798: LDLIBS += -lpthread
        40762798: CC=g++
        40762798: 40762798.o gtest_main.o gtest-all.o gmock-all.o
        

        然后我没有收到任何错误,Valgrind 给出了一个干净的健康证明:

        valgrind  ./40762798 
        ==24351== Memcheck, a memory error detector
        ==24351== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
        ==24351== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
        ==24351== Command: ./40762798
        ==24351== 
        Running main() from gtest_main.cc
        [==========] Running 1 test from 1 test case.
        [----------] Global test environment set-up.
        [----------] 1 test from PainterTest
        [ RUN      ] PainterTest.CanDrawSomething
        [       OK ] PainterTest.CanDrawSomething (84 ms)
        [----------] 1 test from PainterTest (92 ms total)
        
        [----------] Global test environment tear-down
        [==========] 1 test from 1 test case ran. (125 ms total)
        [  PASSED  ] 1 test.
        ==24351== 
        ==24351== HEAP SUMMARY:
        ==24351==     in use at exit: 0 bytes in 0 blocks
        ==24351==   total heap usage: 183 allocs, 183 frees, 117,387 bytes allocated
        ==24351== 
        ==24351== All heap blocks were freed -- no leaks are possible
        ==24351== 
        ==24351== For counts of detected and suppressed errors, rerun with: -v
        ==24351== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
        

        【讨论】:

        • 我使用 Eclipse 构建我的示例。我将尝试使用 makefile 来构建示例。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-01
        • 2021-06-23
        • 1970-01-01
        • 1970-01-01
        • 2011-11-06
        相关资源
        最近更新 更多