Git Product home page Git Product logo

Comments (2)

CheapMeow avatar CheapMeow commented on May 24, 2024 1

It is a common bug about move constructor and copy assignment operator. In these constructor, std::unique_ptr<T> member is moved from rhs to lhs, so it is empty in rhs.

In code, AddClass return a instance of TypeDescriptorBuilder<T>, it calls move constructor.

// reflect.hpp

template <typename T>
details::TypeDescriptorBuilder<T> AddClass(const std::string &name) {
  details::TypeDescriptorBuilder<T> b{name};
  return b;
}

Definition of TypeDescriptorBuilder<T> doesn't implement move constructor, so the default one is called.

// reflect.hpp

template <typename T>
class TypeDescriptorBuilder {
 ...

 private:
  RawTypeDescriptorBuilder raw_builder_;
};

Default move ctor of TypeDescriptorBuilder<T> calls move constructor of RawTypeDescriptorBuilder.

// reflect.hpp

class RawTypeDescriptorBuilder {
  ...

  RawTypeDescriptorBuilder(RawTypeDescriptorBuilder&& rhs) = default;
  RawTypeDescriptorBuilder& operator=(RawTypeDescriptorBuilder&& rhs) = default;

 ...

 private:
  std::unique_ptr<TypeDescriptor> desc_{nullptr};
};

Default move ctor of RawTypeDescriptorBuilder moves std::unique_ptr<TypeDescriptor> desc_.

Now go back to details::TypeDescriptorBuilder<T> AddClass(const std::string &name), after move ctor, the lhs now owns the std::unique_ptr member, the rhs owns empty.

When the program leaves details::TypeDescriptorBuilder<T> AddClass(const std::string &name), the rhs is deleted.

To output the process, modify the code like this:

// reflect.hpp

  template <typename V>
  TypeDescriptorBuilder &AddMemberVar(const std::string &name, V T::*var) {
    std::cout << "AddMemberVar" << std::endl;
    raw_builder_.AddMemberVar(name, var);
    return *this;
  }
// reflect.cpp

RawTypeDescriptorBuilder::~RawTypeDescriptorBuilder() {
    std::cout << "~RawTypeDescriptorBuilder()" << std::endl;
    std::cout << "(desc_ == nullptr) = " << (desc_ == nullptr) << std::endl;
    if(desc_ != nullptr)
        Registry::instance().Register(std::move(desc_));
}

The output is

~RawTypeDescriptorBuilder()
(desc_ == nullptr) = 1
AddMemberVar
AddMemberVar
~RawTypeDescriptorBuilder()
(desc_ == nullptr) = 0

Obviously, the fix is

// reflect.cpp

RawTypeDescriptorBuilder::~RawTypeDescriptorBuilder() {
    if(desc_ != nullptr)
        Registry::instance().Register(std::move(desc_));
}

from cpp-training-season1.

k-ye avatar k-ye commented on May 24, 2024

Thanks for reporting this! Were you just running https://github.com/taichi-dev/cpp-training-season1/blob/main/reflection/src/main.cpp?

There's nothing fancy in ~RawTypeDescriptorBuilder():

RawTypeDescriptorBuilder::~RawTypeDescriptorBuilder() {
Registry::instance().Register(std::move(desc_));
}
. If you print desc_'s address before L14, is it already nullptr?

from cpp-training-season1.

Related Issues (2)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.