CRTP 导致段错误

CRTP causing segfault

我有一个纯虚拟classInterface:

class Interface {
  public:
    virtual ~Interface() noexcept;
    virtual void open()=0;
    virtual void close()=0;
  protected:
    explicit Interface(const string params);
    string params_;
}

然后我有一个摘要 class,我在其中实现我的业务逻辑:

template<typename T>
class AbstractInterface : public Interface {
  public:
    void open() override;
    void close() override;
    void read_is_complete(const vector<byte_array>);
  protected:
    explicit AbstractInterface(const string params);
    virtual ~AbstractInterface() noexcept;
}

然后是使用CRTP多态的接口实现:

class SPInterface : public AbstractInterface<SPInterface> {
  public:
    explicit SPInterface(const string params);
    virtual ~SPInterface() noexcept;
    void open();
    void close();
    void read_is_complete(const vector<byte_array> data);
}

我有一个单元测试,我在其中创建了一个 SPInterface:

的实例
unique_ptr<Interface> intf;
intf.reset(new SPInterface("aaa"));

让它超出范围会调用析构函数 AbstractInterface,后者又会在 AbstractInterface 上调用关闭方法,然后在 this:

上出现段错误
template<typename T>
void AbstractInterface<T>::close() {
  static_cast<T *>(this)->close();
  params_ = "";
}

这令人困惑,因为我已经创建了 class 的实例。 lldb 似乎确认:

AbstractInterface<SPInterface>::close(this=<unavailable>)

Letting this get out of scope calls the destructor AbstractInterface which in turn calls the close method on AbstractInterface and then it segfaults on this:

template<typename T>
void AbstractInterface<T>::close() {
    static_cast<T *>(this)->close();
    params_ = "";
}

您似乎正试图从基 class.
的析构函数中调用派生 class 的方法 这根本不安全,segfault 是可执行文件必须告诉您它不批准的方式。 :-)

即使 CRTP 允许您在(让我说)活对象 上调用属于派生 class 的成员函数,它也不会改变对象被破坏的方式。
不要忘记 bases 和 members 的销毁顺序与构造函数的完成顺序相反 .