[googletest:测试基类具有纯虚方法的派生类时,coredump

问题描述 投票:0回答:2

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

基类看起来像这样:

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;
    }
};

它在常规程序中如预期般运行:

int main()
{ 
    std::cout << "Starting" << std::endl;
    Derived d { 10, false};
    std::this_thread::sleep_for(std::chrono::milliseconds(2000));
    std::cout << "Finishing" << std::endl;
    d.stop();
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}

但是如果我在Google测试中执行它,那么我会得到一个coredump,原因是我在这一行中调用了一个纯虚方法:

workerTh = std::thread{ std::bind(&Base::work, this) };

所以,为什么该行在正常程序中能按预期工作,但在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感到高兴。

有什么想法吗?

谢谢!

c++ multithreading virtual googletest
2个回答
2
投票

不幸的是,您的代码已损坏:在基类构造函数中,您调用了start(),它是虚拟的。这将never调用派生类的start()方法,因为在构造函数中调用时的动态类型是派生类的not。虚拟work()功能也相同。更糟糕的是,取决于线程调度的时间,它可能会或可能不会调用派生类的函数,因为到那时该类型的类型可能已更改为派生类的类型。

测试失败可能只是一个小问题,您的代码已损坏。首先解决该问题,然后查看测试是否仍然失败。


0
投票

根据Ulrich Eckhardt的提示,将对start()的调用从Base构造函数移动到Derived构造函数已解决问题

© www.soinside.com 2019 - 2024. All rights reserved.