Basic tests fail with msvc but work with gcc

Advertisements

I have a simple setup. My base class is:

class PartBase {
  private:
    std::string_view m_Name;


  public:
    explicit PartBase(std::string_view name)
        : m_Name(name){};

    std::string_view getName() { return m_Name; };

    void build() {
        std::cout << "Started building " << getName() << "\n";
        buildPart();
        std::cout << "Building " << getName() << " completed.\n";
    }

    virtual void buildPart(){};
};

Then I have two classes one level higher:

class Rib : public PartBase {
  public:
    explicit Rib(const std::string& partName)
        : PartBase(partName){};

    void buildPart() override {
        std::cout << "Started building " << getName() << "\n";
    };
};

and

class Wing : public PartBase {
  private:
    std::vector<Rib> m_Ribs;

  public:
    explicit Wing(const std::string& partName, spdlog::logger& logger)
        : PartBase(partName, logger){};

    void buildPart() override {
        std::cout << "Started building " << getName() << "\n";
    };
};

Then I have a dumb catch2 test that simply creates a class.

TEST_CASE("WingPartTests", "[tests_wing]") {
    SECTION("test_wing_creation ") {
        // Check creation.
        REQUIRE_NOTHROW(Wing("abc"));

        // Get wing name.
        auto wing = Wing("abc");
        REQUIRE(wing.getName() == "abc");
    }
}

The problem

The problem is that this test passes on Linux with gcc (c++20) no problem. It also builds on msvc, but the tests don’t pass. The test fails with the following output:

7: ..... test\parts\test_wing.cpp(21): FAILED:
7:   REQUIRE( wing.getName() == "abc" )
7: with expansion:
7:   "
7: bc" == "abc"

This I guess makes the test not so "dumb" after all, but I have to admit I have no idea what the problem is. I work on linux, so the only output I get is from the CI. Would anybody know?

>Solution :

You are creating std::string_view with a temporary object that is destroyed when the constructor finishes. It is equivalent to this:

int main() {
    auto wing = std::string_view(std::string("abc"));
    
    // Prints "bc" on Visual Studio
    std::cout << wing << std::endl; 
}

This does not work, as string_view is a simple pointer that does not extend the lifetime of the data:

A typical implementation holds only two members: a pointer to constant CharT and a size.

Change the type of m_Name to std::string to copy the data.

Leave a ReplyCancel reply