C++ googletest:测试基类具有纯虚拟方法的派生类时的coredump

C++ googletest:测试基类具有纯虚拟方法的派生类时的coredump,c++,multithreading,virtual,googletest,C++,Multithreading,Virtual,Googletest,我有一个抽象基类,它具有处理线程生命周期(开始、停止、连接)的逻辑。线程中执行的工作取决于实例化的派生类,并且有几个派生类 基类如下所示: class Base { public: Base(int i, bool b) : i{i}, b{b} { start(); } virtual bool getB() { return b; }; void stop() { stopWorking = true; workerTh.join()

我有一个抽象基类,它具有处理线程生命周期(开始、停止、连接)的逻辑。线程中执行的工作取决于实例化的派生类,并且有几个派生类

基类如下所示:

class Base {
public:
    Base(int i, bool b) : i{i}, b{b}
    {
        start();
    }

    virtual bool getB() { return b; };
    void stop() { stopWorking = true; workerTh.join(); };

protected:
    virtual void start()
    {
        std::cout << "Base start method" << std::endl;
        workerTh = std::thread{ std::bind(&Derived::work, this) };
    };
    virtual void work() = 0;

    std::thread workerTh;
    int i;
    bool b;

    bool stopWorking = false;
};
class Derived : public Base {
public:
    Derived(int i, bool b) : Base(i,b) {};

protected:
    void work()
    {
        std::cout << "Derived Work started!" << std::endl;
        while (not stopWorking)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        }
        std::cout << "Derived Work ended!" << std::endl;
    }
};
那么,为什么这行代码在正常程序中可以正常工作,但在google测试中却崩溃了?我在启动GTest时是否遗漏了什么

这就是测试:

#include "BaseDerived.cc"
#include "gtest/gtest.h"

TEST(BaseDerivedWithThreadTest, FailsCoredumpCallingPureVirtual) {
    Derived d { 10, false };
    ASSERT_FALSE (d.getB());
}

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

[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from BaseDerivedWithThreadTest
[ RUN      ] BaseDerivedWithThreadTest.FailsCoredumpCallingPureVirtual
Base start method
terminate called without an active exception
pure virtual method called
terminate called recursively
Aborted (core dumped)
我可以通过将线程生命周期代码下放到派生类中来克服这个问题,但我发现仅仅为了让googletest开心,它就非常难看

有什么想法吗


谢谢

您的代码不幸被破坏:在基类构造函数中,您调用了
start()
,它是虚拟的。这永远不会调用派生类“
start()
方法,因为在构造函数中调用时的动态类型不是派生类。这同样适用于虚拟
work()
函数。更糟糕的是,根据线程的调度时间,它可能调用派生类的函数,也可能不调用,因为此时它的类型可能已更改为派生类的类型


测试失败可能只是一个转移视线的问题,你的代码被破坏了。首先修复该问题,然后查看测试是否仍然失败。

您的代码不幸被破坏:在基类构造函数中,您调用了
start()
,它是虚拟的。这永远不会调用派生类“
start()
方法,因为在构造函数中调用时的动态类型不是派生类。这同样适用于虚拟
work()
函数。更糟糕的是,根据线程的调度时间,它可能调用派生类的函数,也可能不调用,因为此时它的类型可能已更改为派生类的类型


测试失败可能只是一个转移视线的问题,你的代码被破坏了。首先修复该问题,然后查看测试是否仍然失败。

代码中的两个注意事项:在函数的结束方括号(
}
)后是否放置分号是不一致的。提示:它们完全没有必要。第二,你的代码说每个
孩子
都是
父母
,这与常识相冲突,即每个父母都是孩子,但不是相反。考虑使用<代码> Base< /Cord>和<代码>派生< /代码>,这不存在这个问题。这能回答您的问题吗?关于代码的两个注意事项:在函数的右括号(
}
)后面是否放分号是不一致的。提示:它们完全没有必要。第二,你的代码说每个
孩子
都是
父母
,这与常识相冲突,即每个父母都是孩子,但不是相反。考虑使用<代码> Base< /Cord>和<代码>派生< /代码>,这不存在这个问题。这能回答您的问题吗?可能就是这样:当“this”stil不是合法的“派生”对象时调用线程。然而,我仍然对为什么它在常规程序中100%工作而在gtest中100%失败感到困惑。这可能是因为:当“this”stil不是合法的“派生”对象时调用线程。然而,我仍然对为什么它在常规程序中100%有效而在gtest中100%失败感到困惑。
workerTh = std::thread{ std::bind(&Base::work, this) };
#include "BaseDerived.cc"
#include "gtest/gtest.h"

TEST(BaseDerivedWithThreadTest, FailsCoredumpCallingPureVirtual) {
    Derived d { 10, false };
    ASSERT_FALSE (d.getB());
}

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

[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from BaseDerivedWithThreadTest
[ RUN      ] BaseDerivedWithThreadTest.FailsCoredumpCallingPureVirtual
Base start method
terminate called without an active exception
pure virtual method called
terminate called recursively
Aborted (core dumped)